EntityManager可以不分配ID吗?

时间:2012-06-04 15:04:25

标签: hibernate jpa-2.0

当合并不分配@Id变量时,JPA2中是否存在指定的情况?然后在不触发异常的情况下返回实体的新实例?

说我有这种等级:

@MappedSuperclass
abstract class Bar {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  ...
}

@Entity
@Table(name = "BAR_1S")
@Access(AccessType.PROPERTY)
class Bar1 extends Bar {
  ...
}

@Entity
@Table(name = "BAR_2S")
@Access(AccessType.PROPERTY)
class Bar2 extends Bar {
  ...
}

对于尚未找到的原因,Bar1的实​​例在merge()之后获取id,而Bar2的实例则没有。至少那是它的样子。我一直在努力尝试各种方法。

看起来Hibernate(4.1.4.Final)不希望为该特定类的实例分配id。 : - )

我的问题:

  • 有人有这样的事吗?

  • 有人可以告诉我Hibernate中id的设置在哪里?所以我可以调试代码的这一部分,并找出它为什么会跳过赋值。 IntelliJ似乎没有破坏实体中字段的修改。

编辑 - 环境配置

  • 操作系统:LMDE amd64
  • 数据库:MySQL(5.1.61-2)ConnectJ(5.1.17)
  • JVM:1.7.0_04
  • Hibernate:4.1.4.Final
  • Spring:3.1.1

编辑 - 代码

所有实体类都是Bar的直接子类。只有一个地方定义了@Id。还有一些相同的Bar2案例得到一个id。但特别是Bar2没有。

final Bar1 bar = new Bar1();   JpaTemplate.merge(巴); < - 得到一个id

final Bar2 bar = new Bar2();   JpaTemplate.merge(巴); < - 没有id

该应用程序正在使用Spring的JpaTemplate来合并实体。对于特定类的所有异常,哪个运行正常。

所以,如果我能找到分配id的Hibernate类,我可能会发现我忽略了什么愚蠢的细节。 : - )

2 个答案:

答案 0 :(得分:0)

首先注意:不推荐使用JpaTemplate,不应再使用它。它只是委托给EntityManager的merge()方法,并且都返回一个实体。

以下是JPA规范关于合并的内容:

  

如果X是新的实体实例,则新的托管实体实例X'是   创建并将X的状态复制到新的管理实体中   实例X'。

因此,如果生成了ID,它将被分配给附加的实体,而不是分配给您传递给merge方法的对象。因此,您应该永远不会忽略合并方法的结果。而不是

jpaTemplate.merge(bar);

你应该这样做:

bar = jpaTemplate.merge(bar);

此外,JPA规范也说明了

  

生成的ID不能保证在之后才可用   数据库插入已经发生。

这可能是您没有身份证的另一个原因。使用MySQL的AFAIK,AUTO策略,依赖于数据库中的自动增量ID列,并且只有在插入完成后才能获取ID的值,并且Hibernate等待直到完全需要刷新,因此执行插入。如果您确实需要在合并后立即拥有ID,请执行以下操作:

bar = jpaTemplate.merge(bar);
jpaTemplate.flush();
Long id = bar.getId();

答案 1 :(得分:0)

发现它!合并发生在由@Transactional注释的重载方法中。我假设重载方法将“继承”注释。事实并非如此。

通过使用@Transactional注释重载方法,它似乎有效。

知道这将是一件愚蠢的事情......