有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java查找没有多对多关系的Hibernate对象

我需要使用Hibernate找到所有不含特定过敏原的产品

以下是用于创建数据库表的SQL:

CREATE TABLE ALLERGEN (id integer IDENTITY PRIMARY KEY, name varchar(20), UNIQUE (id), UNIQUE(name));
CREATE TABLE PRODUCT (id integer IDENTITY PRIMARY KEY, name varchar(20), UNIQUE (id), UNIQUE(name));
CREATE TABLE PRODUCT_ALLERGEN (product_id integer, allergen_id integer, UNIQUE (product_id, allergen_id), FOREIGN KEY (product_id) REFERENCES PRODUCT (id), FOREIGN KEY (allergen_id) REFERENCES ALLERGEN (id));

以下是Hibernate注释的Java类:

@Entity
@Table(name = "ALLERGEN")
class Allergen {

    @Id
    @Column(unique = true, nullable = false)
    @GeneratedValue
    private Integer id;
    private String name;

    // ...
}

@Entity
@Table(name = "PRODUCT")
public class Product {

    @Id
    @Column(unique = true, nullable = false)
    @GeneratedValue
    private Integer id;
    private String name;
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(inverseJoinColumns = {@JoinColumn(name = "allergen_id")})
    private final Set<Allergen> allergens = new HashSet<>();

    // ...
}

这个SQL似乎给了我想要的结果,但我不知道如何使用Hibernate标准来表示它

SELECT * FROM PRODUCT WHERE (SELECT COUNT(*) FROM PRODUCT_ALLERGEN WHERE product_id = PRODUCT.id AND allergen_id = 0) = 0;

共 (2) 个答案

  1. # 1 楼答案

    使用Criteria API,您应该能够通过创建产品到过敏原的左连接并检查其是否为空,从而获得所有不含过敏原的产品:

    final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    final CriteriaQuery<Product> c = builder.createQuery(Product.class);
    final Root<Product> root = c.from(Product.class);
    Join<Product, Allergen> allergenJoin = root.join("allergens", JoinType.LEFT);
    c.where(builder.isNull(allergenJoin));
    c.select(root);
    List<Product> = entityManager.createQuery(c).getResultList(); 
    

    注意:我没有包括EntityManager的来源。通常我用注射法,但也有其他方法,比如使用工厂

  2. # 2 楼答案

    此代码使用JPQL获得没有特定过敏原的产品

    List<Product> results = manager.createQuery(
            "SELECT p from Product AS p WHERE (SELECT COUNT(a) FROM p.allergens a WHERE a.name = :an) = 0",
            Product.class)
        .setParameter("an", "nuts")
        .getResultList();