开发者

Spring - hibernate: detached entity passed to persist

I have the following Object:

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; }

As you see this table represents a tree structure. Having the functions:

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);
        }
    }
}

If a call setupPaths i get a "detached entity passed to persist exception". If instead of entityManager.persist(d); i do :

d = entityManager.merge(d);
            d.setPath(tpath);

Nothing happens (the data is not saved in the db). If a call flush, i get detached entity passed to persist exception as well. I suspect it has something to do with me not eagerly loading the parent or children?

edit: After further testing since the above seems really fishy, it seems that every entity i get from entityManager, no matter how i get it (either with em.find(MyObject.class,id or any kind of queries) it is detached right after fetching! I see that from calling

em.contains(myObject)

which always returns false. The problem is that i use the exact same setup on other spring projects with the same database server and it's wroking fine.


After (finally) turning debug info for Hibernate on i saw that the EntityManager was closing the session right after fetch which was wrong since i was using @Transactional annotation. Finally it seems that was a problem with STS (springsource toolsuite) and spring configuration, particularly:

<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>

This supposedly witht the correct maven setup

<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>

should take care of compile-time weaving but something went wrong. I was using plugin 1.2, when i changed that to 1.3.1 it magically worked.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜