Spring Boot get 请求不使用@OneToMany 获取第三级对象
Springboot get rquest not fetching third level object with @OneToMany
我的数据库表设计如下。
使用这种结构,使用 Springboot,我无法获取 TABLE-1 的所有子元素直到 TABLE-3
下面是实体class相同
TABLE-1 (SDKMainCollection.java)
@Entity
@Table(name="sdkmaincollection")
public class SDKMainCollection {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String sdkgroupname;
@JsonIgnore
@OneToMany(mappedBy = "sdkcollectionobj", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<SDKCollection> sdkcollection;
public SDKMainCollection() {
}
public SDKMainCollection(int id,String sdkGroupName) {
this.id= id;
this.sdkgroupname =sdkGroupName;
}
public SDKMainCollection(String sdkGroupName) {
this.sdkgroupname =sdkGroupName;
}
//Getters and Setters
}
TABLE-2 (SDKCollection.java)
@Entity
@Table(name="sdkcollection")
public class SDKCollection {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String sdktitle;
private String sdkid;
private String sdkresourceid;
private String sdkdescription;
private String sdkimageName;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sdkmaincollection_id")
private SDKMainCollection sdkcollectionobj;
@JsonIgnore
@OneToMany(mappedBy = "sdkcolsubobj", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
private Set<Ads> ads;
public SDKCollection() {
}
public SDKCollection(int id, String sdkTitle, String sdkId, String sdkresourceId, String sdkdescription,
String sdkimageName,SDKMainCollection sdkObj) {
this.id = id;
this.sdktitle = sdkTitle;
this.sdkid = sdkId;
this.sdkresourceid = sdkresourceId;
this.sdkdescription = sdkdescription;
this.sdkimageName = sdkimageName;
this.sdkcollectionobj = sdkObj;
}
public SDKCollection(String sdkTitle, String sdkId, String sdkresourceId, String sdkdescription,
String sdkimageName,SDKMainCollection sdkObj) {
this.sdktitle = sdkTitle;
this.sdkid = sdkId;
this.sdkresourceid = sdkresourceId;
this.sdkdescription = sdkdescription;
this.sdkimageName = sdkimageName;
this.sdkcollectionobj = sdkObj;
}
//Getters and Setters
}
TABLE-3 (Ads.java)
@Entity
@Table(name="ads")
public class Ads {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String adtitle;
private String adtag;
private String adtype;
private String imagename;
private String controlid;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sdkcollection_id")
private SDKCollection sdkcolsubobj;
public Ads() {
}
public Ads(int id, String adTitle, String adTag, String adType, String imageName, String controlID,
SDKCollection sdkcollection
) {
this.id = id;
this.adtitle = adTitle;
this.adtag = adTag;
this.adtype = adType;
this.imagename = imageName;
this.controlid = controlID;
this.sdkcolsubobj = sdkcollection;
}
public Ads(String adTitle, String adTag, String adType, String imageName, String controlID
,SDKCollection sdkcollection) {
this.adtitle = adTitle;
this.adtag = adTag;
this.adtype = adType;
this.imagename = imageName;
this.controlid = controlID;
this.sdkcolsubobj = sdkcollection;
}
//Getters and Setters
}
下面是我的控制器class,用于获取元素
@RestController
@RequestMapping("/api/sdk/")
@CrossOrigin
public class GetSDKController {
@Autowired
private SDKMainCollectionRepo sdkMainCollectionRepo;
@Autowired
private SDKCollectionRepo sdkCollectionRepo;
@Autowired
private AdsRepo adsRepo;
@GetMapping("/getAllSDKs")
public List<SDKMainCollection> getAllSDK(){
sdkDataMapper = new SDKDataMapper(sdkMainCollectionRepo,sdkCollectionRepo,adsRepo);
List<SDKMainCollection> totalResp = (List<SDKMainCollection>) sdkMainCollectionRepo.findAll();
System.out.println("getAllSDK = totalResp "+totalResp);
//NOT GETTING WHAT IS EXPECTED
return totalResp;
}
}
低于我的预期,但我得到 Whosebug error
Whosebug
错误日志:
java.lang.WhosebugError: null
at java.util.AbstractCollection.toString(Unknown Source) ~[na:1.8.0_131]
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:328) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at com.dvservices.models.SDKMainCollection.toString(SDKMainCollection.java:59) ~[classes/:na]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at com.dvservices.models.SDKCollection.toString(SDKCollection.java:118) ~[classes/:na]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at java.util.AbstractCollection.toString(Unknown Source) ~[na:1.8.0_131]
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:328) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at com.dvservices.models.SDKMainCollection.toString(SDKMainCollection.java:59) ~[classes/:na]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at com.dvservices.models.SDKCollection.toString(SDKCollection.java:118) ~[classes/:na]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at java.util.AbstractCollection.toString(Unknown Source) ~[na:1.8.0_131]
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:328) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at com.dvservices.models.SDKMainCollection.toString(SDKMainCollection.java:59) ~[classes/:na]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at com.dvservices.models.SDKCollection.toString(SDKCollection.java:118) ~[classes/:na]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at java.util.AbstractCollection.toString(Unknown Source) ~[na:1.8.0_131]
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:328) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
我猜问题可能出在获取最后一个数组并导致 Whosebug 错误。
编辑:
这个问题是因为 OneToMany
和 ManyToOne
在同一个 SDKCollection
class 中,因为它位于层次结构的中间吗?
public class SDKCollection {
........
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sdkmaincollection_id")
private SDKMainCollection sdkcollectionobj;
@JsonIgnore
@OneToMany(mappedBy = "sdkcolsubobj", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
private Set<Ads> ads;
@JsonIgnore
@OneToMany(mappedBy = "sdkcolsubobj", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
private Set<Ads> ads
尝试获取=FetchType.EAGER
好吧,您正在使用 @JsonIgnore 注释广告字段,因此当它被序列化以发送回 HTTP 客户端时,Jackson Serializer 将忽略它,因此如果您想包含广告字段,请删除 @JsonIgnore
另一种变通方法是通过@Transaction 注释您的控制器,这样您就不会遇到惰性初始化异常。 (fetch=FetchType.EAGER 被认为是不好的做法见 https://vladmihalcea.com/eager-fetching-is-a-code-smell/)
更好的解决方案是使用实体图作为获取计划,它与 Spring DATA 集成得非常好,看看
可能有一个案例。
- 在你的条件下尝试
fetch=FetchType.EAGER
- 检查数据库中是否有数据(还有外键关系)。
您缺少 @JsonBackReference 注释,这就是您收到 Whosebug 错误的原因。@JsonIgnore 不是为了解决无限递归问题而设计的,它只是忽略注释 属性 的序列化或反序列化。
在哪里添加
- 在SDKCollection.java
私有 SDKMainCollection sdkcollectionobj; 向后引用 SDKMaincollection,
- in Ads.java private SDKCollection sdkcolsubobj 向后引用 SDKCollection
以上两者都应使用 @JsonBackReference 进行注释
希望对你有帮助。
所以我终于能够解决错误。
因为我有三级层次结构,这是我完成这项工作的唯一方法。
- 已从 child table 个实体中删除 ManyToOne
- 仅在
@OneToMany
中保留了 cascade = CascadeType.ALL,orphanRemoval = true
- 没有 parent table 是从 child tables
中用 @ManyToOne
引用的
所以变化如下
TABLE-1 (SDKMainCollection.java)
@Entity
@Table(name="sdkmaincollection")
public class SDKMainCollection {
...
...
@OneToMany(cascade = CascadeType.ALL,orphanRemoval = true)
private List<Sdkcollection> sdkCollection = new ArrayList<Sdkcollection>();
//No Constructor required
//Kept only getters and setters
}
TABLE-2 (SDKCollection.java)
@Entity
@Table(name="sdkcollection")
public class SDKCollection {
...
...
@OneToMany(cascade = CascadeType.ALL,orphanRemoval = true)
private List<Ads> ads = new ArrayList<Ads>();
//No parent table with @ManyToOne was refered
//No Constructor required
//Kept only getters and setters
}
TABLE-3 (Ads.java)
@Entity
@Table(name="ads")
public class Ads {
...
...
//No parent table with @ManyToOne was refered
//No Constructor required
//Kept only getters and setters
}
Hibernate 为层次结构创建了关系和额外的 table。 Child table 最后一级的详细信息已检索到,没有任何 Whosebuger 错误。
我的数据库表设计如下。
使用这种结构,使用 Springboot,我无法获取 TABLE-1 的所有子元素直到 TABLE-3
下面是实体class相同
TABLE-1 (SDKMainCollection.java)
@Entity
@Table(name="sdkmaincollection")
public class SDKMainCollection {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String sdkgroupname;
@JsonIgnore
@OneToMany(mappedBy = "sdkcollectionobj", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<SDKCollection> sdkcollection;
public SDKMainCollection() {
}
public SDKMainCollection(int id,String sdkGroupName) {
this.id= id;
this.sdkgroupname =sdkGroupName;
}
public SDKMainCollection(String sdkGroupName) {
this.sdkgroupname =sdkGroupName;
}
//Getters and Setters
}
TABLE-2 (SDKCollection.java)
@Entity
@Table(name="sdkcollection")
public class SDKCollection {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String sdktitle;
private String sdkid;
private String sdkresourceid;
private String sdkdescription;
private String sdkimageName;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sdkmaincollection_id")
private SDKMainCollection sdkcollectionobj;
@JsonIgnore
@OneToMany(mappedBy = "sdkcolsubobj", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
private Set<Ads> ads;
public SDKCollection() {
}
public SDKCollection(int id, String sdkTitle, String sdkId, String sdkresourceId, String sdkdescription,
String sdkimageName,SDKMainCollection sdkObj) {
this.id = id;
this.sdktitle = sdkTitle;
this.sdkid = sdkId;
this.sdkresourceid = sdkresourceId;
this.sdkdescription = sdkdescription;
this.sdkimageName = sdkimageName;
this.sdkcollectionobj = sdkObj;
}
public SDKCollection(String sdkTitle, String sdkId, String sdkresourceId, String sdkdescription,
String sdkimageName,SDKMainCollection sdkObj) {
this.sdktitle = sdkTitle;
this.sdkid = sdkId;
this.sdkresourceid = sdkresourceId;
this.sdkdescription = sdkdescription;
this.sdkimageName = sdkimageName;
this.sdkcollectionobj = sdkObj;
}
//Getters and Setters
}
TABLE-3 (Ads.java)
@Entity
@Table(name="ads")
public class Ads {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String adtitle;
private String adtag;
private String adtype;
private String imagename;
private String controlid;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sdkcollection_id")
private SDKCollection sdkcolsubobj;
public Ads() {
}
public Ads(int id, String adTitle, String adTag, String adType, String imageName, String controlID,
SDKCollection sdkcollection
) {
this.id = id;
this.adtitle = adTitle;
this.adtag = adTag;
this.adtype = adType;
this.imagename = imageName;
this.controlid = controlID;
this.sdkcolsubobj = sdkcollection;
}
public Ads(String adTitle, String adTag, String adType, String imageName, String controlID
,SDKCollection sdkcollection) {
this.adtitle = adTitle;
this.adtag = adTag;
this.adtype = adType;
this.imagename = imageName;
this.controlid = controlID;
this.sdkcolsubobj = sdkcollection;
}
//Getters and Setters
}
下面是我的控制器class,用于获取元素
@RestController
@RequestMapping("/api/sdk/")
@CrossOrigin
public class GetSDKController {
@Autowired
private SDKMainCollectionRepo sdkMainCollectionRepo;
@Autowired
private SDKCollectionRepo sdkCollectionRepo;
@Autowired
private AdsRepo adsRepo;
@GetMapping("/getAllSDKs")
public List<SDKMainCollection> getAllSDK(){
sdkDataMapper = new SDKDataMapper(sdkMainCollectionRepo,sdkCollectionRepo,adsRepo);
List<SDKMainCollection> totalResp = (List<SDKMainCollection>) sdkMainCollectionRepo.findAll();
System.out.println("getAllSDK = totalResp "+totalResp);
//NOT GETTING WHAT IS EXPECTED
return totalResp;
}
}
低于我的预期,但我得到 Whosebug error
Whosebug
错误日志:
java.lang.WhosebugError: null
at java.util.AbstractCollection.toString(Unknown Source) ~[na:1.8.0_131]
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:328) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at com.dvservices.models.SDKMainCollection.toString(SDKMainCollection.java:59) ~[classes/:na]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at com.dvservices.models.SDKCollection.toString(SDKCollection.java:118) ~[classes/:na]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at java.util.AbstractCollection.toString(Unknown Source) ~[na:1.8.0_131]
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:328) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at com.dvservices.models.SDKMainCollection.toString(SDKMainCollection.java:59) ~[classes/:na]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at com.dvservices.models.SDKCollection.toString(SDKCollection.java:118) ~[classes/:na]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at java.util.AbstractCollection.toString(Unknown Source) ~[na:1.8.0_131]
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:328) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at com.dvservices.models.SDKMainCollection.toString(SDKMainCollection.java:59) ~[classes/:na]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at com.dvservices.models.SDKCollection.toString(SDKCollection.java:118) ~[classes/:na]
at java.lang.String.valueOf(Unknown Source) ~[na:1.8.0_131]
at java.lang.StringBuilder.append(Unknown Source) ~[na:1.8.0_131]
at java.util.AbstractCollection.toString(Unknown Source) ~[na:1.8.0_131]
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:328) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
我猜问题可能出在获取最后一个数组并导致 Whosebug 错误。
编辑:
这个问题是因为 OneToMany
和 ManyToOne
在同一个 SDKCollection
class 中,因为它位于层次结构的中间吗?
public class SDKCollection {
........
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sdkmaincollection_id")
private SDKMainCollection sdkcollectionobj;
@JsonIgnore
@OneToMany(mappedBy = "sdkcolsubobj", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
private Set<Ads> ads;
@JsonIgnore
@OneToMany(mappedBy = "sdkcolsubobj", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
private Set<Ads> ads
尝试获取=FetchType.EAGER
好吧,您正在使用 @JsonIgnore 注释广告字段,因此当它被序列化以发送回 HTTP 客户端时,Jackson Serializer 将忽略它,因此如果您想包含广告字段,请删除 @JsonIgnore
另一种变通方法是通过@Transaction 注释您的控制器,这样您就不会遇到惰性初始化异常。 (fetch=FetchType.EAGER 被认为是不好的做法见 https://vladmihalcea.com/eager-fetching-is-a-code-smell/)
更好的解决方案是使用实体图作为获取计划,它与 Spring DATA 集成得非常好,看看
可能有一个案例。
- 在你的条件下尝试
fetch=FetchType.EAGER
- 检查数据库中是否有数据(还有外键关系)。
您缺少 @JsonBackReference 注释,这就是您收到 Whosebug 错误的原因。@JsonIgnore 不是为了解决无限递归问题而设计的,它只是忽略注释 属性 的序列化或反序列化。
在哪里添加
- 在SDKCollection.java 私有 SDKMainCollection sdkcollectionobj; 向后引用 SDKMaincollection,
- in Ads.java private SDKCollection sdkcolsubobj 向后引用 SDKCollection
以上两者都应使用 @JsonBackReference 进行注释 希望对你有帮助。
所以我终于能够解决错误。
因为我有三级层次结构,这是我完成这项工作的唯一方法。
- 已从 child table 个实体中删除 ManyToOne
- 仅在
@OneToMany
中保留了 - 没有 parent table 是从 child tables 中用
cascade = CascadeType.ALL,orphanRemoval = true
@ManyToOne
引用的
所以变化如下
TABLE-1 (SDKMainCollection.java)
@Entity
@Table(name="sdkmaincollection")
public class SDKMainCollection {
...
...
@OneToMany(cascade = CascadeType.ALL,orphanRemoval = true)
private List<Sdkcollection> sdkCollection = new ArrayList<Sdkcollection>();
//No Constructor required
//Kept only getters and setters
}
TABLE-2 (SDKCollection.java)
@Entity
@Table(name="sdkcollection")
public class SDKCollection {
...
...
@OneToMany(cascade = CascadeType.ALL,orphanRemoval = true)
private List<Ads> ads = new ArrayList<Ads>();
//No parent table with @ManyToOne was refered
//No Constructor required
//Kept only getters and setters
}
TABLE-3 (Ads.java)
@Entity
@Table(name="ads")
public class Ads {
...
...
//No parent table with @ManyToOne was refered
//No Constructor required
//Kept only getters and setters
}
Hibernate 为层次结构创建了关系和额外的 table。 Child table 最后一级的详细信息已检索到,没有任何 Whosebuger 错误。