2011-07-03 72 views
2

我有以下對象:春天 - 休眠:通過堅持脫離實體

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

什麼也沒有發生(數據未保存在數據庫)。如果一個調用刷新,我得到分離的實體傳遞給持久異常。我懷疑這和我有關,不是急於加載父母或孩子?因爲上面看起來真的很可疑,看起來我從entityManager得到的每一個實體,無論我如何得到它(無論是用em.find(MyObject.class,id還是任何種類的查詢)它被取後分離吧!我看到,從調用

em.contains(myObject) 

它總是返回false。問題是,我用其他的Spring項目完全相同的設置使用相同的數據庫服務器,它的wroking罰款。

回答

3

在(終於)轉爲Hibernate的調試信息之後,我看到EntityManager在獲取哪個w後立即關閉會話因爲我使用了@Transactional註解,所以這是錯誤的。最後,它似乎是與STS(SpringSource的工具包)和彈簧的配置,尤其是一個問題:

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

這理應witht正確的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它神奇地工作。