Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JPA2.0按业务密钥检索实体_Jpa - Fatal编程技术网

JPA2.0按业务密钥检索实体

JPA2.0按业务密钥检索实体,jpa,Jpa,我知道有很多类似的帖子,但是我找不到一个明确的答案来回答我的问题 为了尽可能简单,假设我有这样一个实体: @Entity public class Person implements Serializable { @Id private Long id; // PK private String name; // business key /* getters and setters */ /* override equals() and hashC

我知道有很多类似的帖子,但是我找不到一个明确的答案来回答我的问题

为了尽可能简单,假设我有这样一个实体:

@Entity
public class Person implements Serializable {
  @Id
  private Long id;     // PK

  private String name; // business key

  /* getters and setters */

  /* 
     override equals() and hashCode() 
     to use the **name** field 
   */
}
因此,
id
是主键,
name
是业务键。 假设我得到了一个名字列表,其中可能有重复的名字,我想存储这些名字。 如果我只是为每个名称创建一个对象,并让JPA将其持久化,那么我的最终表将包含重复的名称——这是不可接受的

我的问题是,考虑到我在下面描述的备选方案和(特别欢迎)您自己的备选方案,您认为什么是最好的方法

可能的解决方案1:检查实体管理器 在创建新的person对象之前,请检查是否已管理具有相同人名的对象。 问题:实体管理器只能按主键查询。有什么我不知道的解决办法吗

可能的解决方案2:通过查询查找对象 问题1:为大型集合浪费内存,因为实体管理器基本上就是这样做的(但不完全如此!)

问题2:假设我有一个更复杂的模式,在最初编写应用程序之后,我的应用程序关闭,再次启动,需要重新加载数据库。如果所有表都显式加载到em中,那么我可以很容易地重新填充字典(每个实体一个),但是如果我使用延迟获取和/或级联读取,那么就不那么容易了

我最近开始使用JPA(我使用EclipseLink),所以这里可能缺少一些基本的东西,因为这个问题似乎归结为一种非常常见的使用模式


请开导我

我能想到的最好的解决方案非常简单,使用


确保字段可以(正确)用作键的唯一方法是在其上创建唯一约束。您可以使用
@UniqueConstraint(columnNames=“name”)
或使用
@Column(unique=true)
执行此操作

尝试插入重复密钥时,EntityManager(实际上是DB)将抛出异常。对于手动设置的主键,这种情况也是如此


防止异常的唯一方法是对键进行选择并检查它是否存在。

这难道不会让我的第二次插入失败吗?我想要的是获取实体管理器已经拥有的对象的引用。基本上,em.find的功能与em.find相同,但对于我的业务密钥来说,添加一个唯一的约束确实是一件好事,但并不能实现我想要实现的目标。查询真的是唯一的方法吗?让我困惑的是,实体管理器内部有某种类型的对象集合(对于这些对象,我覆盖了
equals()
hashCode()
),但无法访问。我的3号解决方案确实复制了这一功能(这听起来是错误的…)。我不敢相信这是一个未知的问题。@cornuz是的,查询是唯一的方法,否则你怎么知道数据库中有什么?嗯,em知道!(至少关于附加的实体)@cornuz你不能依赖它,如果你昨天坚持了某件事,今天又试图坚持一个具有相同密钥的实体会怎么样?那么多个用户/线程呢?我承认我现在忽略了并发性问题,但是我在使用PK时不应该有完全相同的问题吗?在我的解决方案2中,当您发出一个查询时,是否总是向数据库触发该查询?如果em的内存中已经有了所有对象,它还会转到DB吗?
Query query = em.createQuery("SELECT p FROM Person p WHERE p.name = ...");
List<Person> list = query.getResultList();
Map<String,Person> personDict = new HashMap<String,Person>();
for(String n : incomingNames) {
  Person p = personDict.get(n);
  if (p == null) {
    p = new Person();
    p.setName(n);
    em.persist(p);
    personDict.put(n,p);
  }
  // do something with it
}
@Entity
@UniqueConstraint(columnNames="name")
public class Person implements Serializable {
    @Id
    private Long id;     // PK

    private String name; // business key
}