Spring - hibernate:传递给分离的实体持久化

时间:2011-07-03 21:45:00

标签: hibernate spring jpa

我有以下对象:

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项目上使用完全相同的设置,并且它正在好转。

1 个答案:

答案 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时,它神奇地工作了。