Java 调用EntityManager.merge()时未设置Id
我在2个对象父对象和子对象之间有一个简单的单域关联,如下所示 母实体Java 调用EntityManager.merge()时未设置Id,java,hibernate,jpa,Java,Hibernate,Jpa,我在2个对象父对象和子对象之间有一个简单的单域关联,如下所示 母实体 @Entity public class Parent { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; @Version private Long version; @OneToMany(cascade
@Entity
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@Version
private Long version;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
List<Child> children = new ArrayList<Child>();
....
}
下面是我的测试,它加载一个现有的父级并添加一个子级,并在父级上调用EntityManager.merge()
@Test
public void testParent(){
Parent parent = (Parent) dao.loadParent(Parent.class, parentId);
Child c = new Child();
c.setName("c");
parent.getChildren().add(c);
dao.mergeEntity(parent);
Assert.assertNotNull(c.getId());
}
测试id主键的断言失败。我看到记录与自动分配的主键一起正确插入数据库
所有my DAO调用都围绕事务进行包装,并根据需要进行传播。由于您的id是由数据库设置的,JPA/Hibernate只能在SQL语句发送到数据库后进行设置。如果将Hibernate配置为显示sql语句或将日志更改为调试,则在调用
mergeEntity
时可能会看到没有发出sql语句
使测试工作的一种方法应该是在对子id进行断言之前添加em.flush()
管理事务的方式可能会有问题,但需要查看DAO的代码以及在单元测试中获取DAO引用的方式 EntityManager.merge(..)
获取一个实例并返回一个受管理的实例。如果是临时实例,则返回一个新实例(不修改原始实例)
因此,您的
mergeEntity(…)
方法应该返回em.merge(entity)
您应该提供更多信息,这是spring还是ejb应用程序?您可以发布dao.mergeEntity(父)的代码吗?事务由spring处理下面是我的dao代码@Transactional(propagation=propagation.REQUIRED)公共对象mergeEntity(对象实体){return em.merge(entity);}@Transactional(propagation=propagation.REQUIRED)公共对象mergeEntity(对象实体){return em.merge(entity);}
@Test
public void testParent(){
Parent parent = (Parent) dao.loadParent(Parent.class, parentId);
Child c = new Child();
c.setName("c");
parent.getChildren().add(c);
dao.mergeEntity(parent);
Assert.assertNotNull(c.getId());
}