在Hibernate中通过映射的复合主键查找条目

时间:2018-08-21 21:04:26

标签: java sql hibernate hibernate-mapping composite-primary-key

具有双向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,这可能是因为ProductCompany未存储在数据库中并且无法计算其哈希值,至少这是我可以从堆栈跟踪中得出的结果:

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可以自动对数据进行处理。有办法使它起作用吗?

0 个答案:

没有答案