具有双向ManyToOne关系,是否可以使用entityManager.find(ComponundPrimaryKey.class, new CompooundPrimaryKey(...)
来获取数据?
这些是我的课程:
@Entity
public class Company implements Serializable {
@Id
@GeneratedValue
private Integer id;
private String name;
@OneToMany(
mappedBy = "companyProduct.company",
cascade = CascadeType.ALL
)
private List<ProductRating> ratings = new ArrayList<>();
// Getters, setters, hashCode, equals...
public void addProductAndRating(Product product, Integer rating) {
CompanyProduct companyProduct = new CompanyProduct();
companyProduct.setCompany(this);
companyProduct.setProduct(product);
ProductRating productRating = new ProductRating();
productRating.setCompanyProduct(companyProduct);
productRating.setRating(rating);
ratings.add(productRating);
product.getRatings().add(productRating);
}
}
@Entity
public class Product implements Serializable {
@Id
@GeneratedValue
private Integer id;
private String type;
@OneToMany(
mappedBy = "companyProduct.product",
cascade = CascadeType.ALL
)
List<ProductRating> ratings = new ArrayList<>();
// Getters, setters, hashCode, equals...
}
@Embeddable
public class CompanyProduct implements Serializable {
@ManyToOne
private Company company;
@ManyToOne
private Product product;
// Getters, setters, hashCode, equals...
}
@Entity
public class ProductRating implements Serializable {
@EmbeddedId
private CompanyProduct companyProduct;
private Integer rating;
// Getters, setters, hashCode, equals...
}
现在我可以用这种方式存储数据:
Company company = new Company();
company.setName("ACME");
Product product1 = new Product();
product1.setName("Toothbrush");
Product product2 = new Product();
product2.setName("Pencil");
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(company);
session.save(product1);
session.save(product2);
company.addProductAndRating(product1, 10);
company.addProductAndRating(product2, 4);
session.getTransaction().commit();
session.close();
现在,我想使用公司名称和产品名称来获得产品的评级。如果保留对实体的引用,则可以执行以下操作:
CompanyProduct companyProduct = new CompanyProduct();
companyProduct.setCompany(company);
companyProduct.setProduct(product1);
ProductRating rating = session.find(ProductRating.class, companyProduct);
这很好用。但是,我需要以某种方式获取参考。我试图做这样的事情,但是不起作用:
Product product = new Product();
product.setName("Pencil");
Company company = new Company();
company.setName("ACME");
CompanyProduct companyProduct = new CompanyProduct();
companyProduct.setCompany(company);
companyProduct.setProduct(product);
ProductRating rating = session.find(ProductRating.class, companyProduct);
这可能引发NullPointerException
,这可能是因为Product
和Company
未存储在数据库中并且无法计算其哈希值,至少这是我可以从堆栈跟踪中得出的结果:
Exception in thread "main" java.lang.NullPointerException
at org.hibernate.type.descriptor.java.AbstractTypeDescriptor.extractHashCode(AbstractTypeDescriptor.java:65)
at org.hibernate.type.AbstractStandardBasicType.getHashCode(AbstractStandardBasicType.java:203)
at org.hibernate.type.AbstractStandardBasicType.getHashCode(AbstractStandardBasicType.java:208)
at org.hibernate.type.EntityType.getHashCode(EntityType.java:355)
at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:242)
at org.hibernate.engine.spi.EntityKey.generateHashCode(EntityKey.java:61)
at org.hibernate.engine.spi.EntityKey.<init>(EntityKey.java:54)
at org.hibernate.internal.AbstractSharedSessionContract.generateEntityKey(AbstractSharedSessionContract.java:467)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:112)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1239)
at org.hibernate.internal.SessionImpl.access$1900(SessionImpl.java:203)
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.doLoad(SessionImpl.java:2804)
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2778)
at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3407)
at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3371)
我知道我自己可以编写一个SQL查询来获取数据,但是我认为Hibernate可以自动对数据进行处理。有办法使它起作用吗?