我有以下对象:
public class Constraint {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
int id;
String name;
String description;
String path;
int level;
@ManyToOne
@JoinColumn(name="parent_id")
Constraint parent;
@OneToMany
@JoinColumn(name="parent_id")
Set<Constraint> children;
@ManyToOne
@JoinColumn(name="type_id")
ConstraintType type; }
如您所见,此表表示树结构。有这些功能:
public List<Constraint> getAllDescendantsOfConstraint(Integer id) {
StringBuilder sb = new StringBuilder();
sb.append("WITH RECURSIVE tree as ");
sb.append("( ");
sb.append(" select * from constraints where id = :id ");
sb.append(" union all ");
sb.append(" select a.* from constraints a, tree b where a.parent_id = b.id ");
sb.append(") ");
sb.append("select * from tree where id <> :id ");
Query q = entityManager.createNativeQuery(sb.toString(), Constraint.class);
q.setParameter("id", id);
return (List<Constraint>) q.getResultList();
}
@Transactional
public void setupPaths() {
Query q = entityManager.createQuery("from Constraint", Constraint.class);
@SuppressWarnings("unchecked")
List<Constraint> constraints = (List<Constraint>) q.getResultList();
for(Constraint c : constraints) {
List<Constraint> descendants = getAllDescendantsOfConstraint(c.getId());
for(Constraint d : descendants) {
String tpath;
if((tpath = d.getPath()) == null || d.getPath().equals(""))
tpath = String.valueOf(c.getId());
else
tpath = d.getPath() + "." + String.valueOf(c.getId());
d.setPath(tpath);
entityManager.persist(d);
}
}
}
如果调用setupPaths我得到“传递给持久异常的分离实体”。
如果我代替entityManager.persist(d);
:
d = entityManager.merge(d);
d.setPath(tpath);
没有任何反应(数据未保存在数据库中)。如果调用flush,我将分离的实体传递给持久异常。我怀疑这与我有什么关系而不是急切地加载父母或孩子?
编辑:经过进一步的测试,因为上面看起来真的很腥,似乎我从entityManager获得的每个实体,无论我如何得到它(使用em.find(MyObject.class,id或任何类型的查询)它取出后立即分离!我从调用
看到了em.contains(myObject)
总是返回false。问题是我在使用相同数据库服务器的其他spring项目上使用完全相同的设置,并且它正在好转。
答案 0 :(得分:3)
在(最后)关闭Hibernate的调试信息后,我看到EntityManager在fetch之后正在关闭会话,因为我使用的是@Transactional注释,这是错误的。最后,似乎STS(springource tooluite)和弹簧配置存在问题,特别是:
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
这应该是正确的maven设置
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.3.1</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>compile</id>
<configuration>
<source>${java-version}</source>
<target>${java-version}</target>
<verbose>false</verbose>
<outxml>true</outxml>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<source>${java-version}</source>
<target>${java-version}</target>
</configuration>
</plugin>
应该注意编译时编织,但出了点问题。我使用的是插件1.2,当我将其改为1.3.1时,它神奇地工作了。