我在Spring Boot应用程序中添加了两个实体之间的多对多关系。我有以下映射:
Business.java:
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "business_vendor",
joinColumns = @JoinColumn(name = "business_id"),
inverseJoinColumns = @JoinColumn(name = "vendor_id"))
@JSON(include = false)
protected List<Vendor> vendors;
Vendor.java
@ManyToMany(cascade = CascadeType.ALL, mappedBy = "vendors")
@JSON(include = false)
protected List<Business> businesses;
我可以将商家添加到商家,然后将其保存到数据库中。但是,当(在新请求中)我加载业务然后调用business.getVendors()
时,我得到一个空列表。我可以从应用程序日志中看到Hibernate从链接表中选择,如果我手动对数据库运行Hibernate生成的查询,我会看到我想要的一行。我已经尝试将FetchMode切换为eager并尝试删除CascadeType.ALL
,这两者都没有帮助。
此应用程序在Hibernate 4.3.11上(由于“原因”,此时无法升级)。
编辑:这是一个最小的例子:
public List<Vendor> getVendorsForBusiness(UUID businessId) {
Business business = businessRepository.findOne(businessId.toString());
return business.getVendors();
}
我希望这会返回一个包含1个供应商的List,但是我得到一个空列表,即使数据库中的链接表中有一行。
编辑2:这是我正在使用的持久化方法的相关部分,它在business_vendor表中成功创建了一行:
public void addVendorToBusiness(UUID businessId, UUID vendorId) {
Vendor vendor = vendorRepository.findOne(vendorId.toString());
Business business = businessRepository.findOne(businessId.toString());
business.getVendors().add(vendor);
vendor.getBusinesses().add(business); // This line doesn't make a difference
businessRepository.save(business);
}
答案 0 :(得分:0)
只需使用双向策略即可。像这样:
Business.java
@Entity
@Table(name = "BUSINESS")
public class Business implements Serializable {
@Id
@GeneratedValue
@Column(name = "ID")
private Long id;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "business_vendor",
joinColumns = @JoinColumn(name = "business_id"),
inverseJoinColumns = @JoinColumn(name = "vendor_id"))
//@JSON(include = false)
private List<Vendor> vendors;
public Business() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<Vendor> getVendors() {
return vendors;
}
public void setVendors(List<Vendor> vendors) {
this.vendors = vendors;
}
}
Vendor.java
@Entity
@Table(name = "VENDOR")
public class Vendor implements Serializable {
@Id
@GeneratedValue
@Column(name = "ID")
private Long id;
@ManyToMany(cascade = CascadeType.ALL, mappedBy = "vendors", fetch = FetchType.EAGER)
// @JSON(include = false)
private List<Business> businesses;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<Business> getBusinesses() {
return businesses;
}
public void setBusinesses(List<Business> businesses) {
this.businesses = businesses;
}
public Vendor() {
}
}
Main.java
public class Main {
private static final SessionFactory SESSION_FACTORY = new AnnotationConfiguration().configure().buildSessionFactory();
private Session session;
private Transaction transaction;
public static void main(String[] args) {
Main main = new Main();
main.save();
List<Vendor> vList = main.getVendorFromBusinessId(2L);
main.displayVendors(vList);
SESSION_FACTORY.close();
System.exit(0);
}
private void save() {
this.session = SESSION_FACTORY.openSession();
this.transaction = null;
try {
this.transaction = this.session.beginTransaction();
Business b1 = new Business();
Business b2 = new Business();
Business b3 = new Business();
Vendor v1 = new Vendor();
Vendor v2 = new Vendor();
List<Business> bList = new ArrayList<>();
bList.add(b1);
bList.add(b2);
bList.add(b3);
List<Vendor> vList = new ArrayList<>();
vList.add(v1);
vList.add(v2);
b1.setVendors(vList);
b2.setVendors(vList);
b3.setVendors(vList);
v1.setBusinesses(bList);
v2.setBusinesses(bList);
this.session.save(b1);
this.session.save(b2);
this.session.save(b3);
this.transaction.commit();
} catch (Exception e) {
if (this.transaction == null) {
this.transaction.rollback();
}
} finally {
this.session.close();
}
}
private List<Vendor> getVendorFromBusinessId(Long businessId) {
List<Vendor> vList = null;
this.session = SESSION_FACTORY.openSession();
this.transaction = null;
try {
this.transaction = this.session.beginTransaction();
Business business = (Business) this.session.get(Business.class, businessId);
vList = business.getVendors();
this.transaction.commit();
} catch (Exception e) {
if (this.transaction == null) {
this.transaction.rollback();
}
} finally {
this.session.close();
}
return vList;
}
private void displayVendors(List<Vendor> vList) {
if (vList != null) {
System.out.print("Vendor List IDs: ");
vList.forEach((vendor) -> {
System.out.print(vendor.getId() + " ");
});
System.out.println();
}
}
}
希望这能解决您的问题。
我的输出: My Output Image
答案 1 :(得分:0)
在数据库中,我们使用UUID作为主键。但是,构建此应用程序的人员决定不使用Java UUID
类型,而是使用String
作为UUID。因此,有时应用程序会将小写的UUID发送到数据库,有时它会发送一个大写的UUID。数据库并不关心,因为SQL Server中的UUID不区分大小写,但Java Strings
区分大小写,因此Hibernate无法识别具有小写UUID的Business
与具有大写UUID的Business
。因此,在将它们发送到数据库之前,我必须.toString().toUpperCase()
所有ID,以确保它们是相同的。
当然,Java UUID
不区分大小写,所以如果构建此软件的人只使用那些而不是String
s,那么整个问题就可以避免了。
答案 2 :(得分:0)
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "business_vendor",
joinColumns = @JoinColumn(name = "business_id"**, referencedColumnName = "enter business Id name"**),
inverseJoinColumns = @JoinColumn(name = "vendor_id", **referencedColumnName = "enter vendor Id name"** ))
@JSON(include = false)
protected List<Vendor> vendors;
**OR**
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "business_vendor",
joinColumns = @JoinColumn(**name = "tablename_idname"**),
inverseJoinColumns = @JoinColumn(**name = "tablename_idname"**))
@JSON(include = false)
protected List<Vendor> vendors;