当合并不分配@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似乎没有破坏实体中字段的修改。
编辑 - 环境配置
编辑 - 代码
所有实体类都是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类,我可能会发现我忽略了什么愚蠢的细节。 : - )
答案 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注释重载方法,它似乎有效。
知道这将是一件愚蠢的事情......