java - 如何在 JPA 2.0 中子查询多个键值组合的映射?

标签 java sql java-ee-7 jpa-2.1

我有以下实体(示例):

@Entity
@Table(name = "person")
public class Person implements Serializable {

  @Id
  @Column(name = "person_id", columnDefinition = "UUID")
  private UUID userId;

  @Column(name = "name")
  private String name;


  @ElementCollection
  @MapKeyColumn(name = "phonetype")
  @Column(name = "number")
  @CollectionTable(name = "person_phones", joinColumns = @JoinColumn(name = "userId"))
  private Map<String, String> phoneNumbers;

}

现在,phoneNumbers 是 String,在这个例子中是 String。假设键是类型(如“移动”、“家庭”、“办公室”、“传真”、“寻呼机”...),值是任何文本格式的实际数字。

我想查询一个有两个电话号码的人:

Select * From person where
   in his phone_numbers exists phonetype = 'home' and number = '0-123-456'
   and also in his phone_numbers exists phonetype = 'mobile' and number = '9-876-421'
   (and possibly, dynamically others)
   and name = 'John'

我已经构建了一个有效的 sql 子查询:

select home.userId from
(
    (SELECT userId from person_phones
    where (phonetype = 'home' and number = '0-123-456'))
) as home,
(
    (SELECT userId from person_phones
    where (phonetype = 'mobile' and number = '9-876-421'))
) as mobile
where home.userId = mobile.userId

如前所述,这只是一个 sql 子查询。我正在我的项目中编写 JPA 2.1 条件查询。这看起来异常复杂。谁能给我一个提示?

最佳答案

有一个类似的问题,使用多个内部连接而不是子查询解决了它。

EntityManagerFactory emf =  Persistence.createEntityManagerFactory("Person-Test");
    EntityManager em = emf.createEntityManager();

    Map<String, String> phoneNumbers = new HashMap<>();
    phoneNumbers.put("home","0-123-456");
    phoneNumbers.put("mobile","9-876-421");

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Person> query = cb.createQuery(Person.class);
    Root<Person> personRoot = query.from(Person.class);
    query.select(personRoot);

    phoneNumbers.forEach((k, v) -> {
        MapJoin<Person, String, String> phoneNrJoinJoin = personRoot.joinMap("phoneNumbers");
        phoneNrJoinJoin.on(cb.equal(phoneNrJoinJoin.key(), k), cb.equal(phoneNrJoinJoin.value(), v));
    });

    query.where(cb.equal(personRoot.get("name"), "John"));

    List<Person> people = em.createQuery(query).getResultList();

这导致以下 hibernate 查询(为清楚起见重命名别名)

SELECT person.person_id, person.name
FROM person 
INNER JOIN person_phones a
ON person.person_id = a.userid
AND (a.phonetype = ? AND a.NUMBER = ?) 
INNER JOIN person_phones b
on person.person_id=b.userId 
and (b.phonetype=? and b.number = ? )
WHERE
person.name = ?;

它返回所有提到的电话号码都匹配的人类型的元组。

关于java - 如何在 JPA 2.0 中子查询多个键值组合的映射?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38397120/

相关文章:

java - Spark Streaming gc 设置问题

sql - Scala Spark Cassandra 在主键匹配上更新或插入行

SQL FETCH、游标和 RPG

mysql - 为什么 WHERE 子句中具有不同外键的相同 SQL 查询会获得不同的性能?

cdi - CDI 2.0 可以与 weblogic 12c 一起使用吗?

Java:找不到适合 Scanner(int) 的构造函数

java - JBoss 焊接 CDI : Inject the same instance in two different Objects

java - Db4o 数据连接错误

jakarta-ee - 在 Java EE 7 应用程序中使用 JDK 8 时出现 java.lang.ClassNotFoundException : com. sun.corba.ee.impl.orb.ORBSingleton