2011-11-18 38 views
0

我正在使用JPA的獨立應用程序使用JPA進行對象持久化,而提供程序是Hibernate。現在,當我堅持一個實體並調用EntityTransaction的commit()時,實體被持久化到數據庫。如果在約束等數據庫錯誤有一個例外,當我嘗試回滾我得到一個java.lang.IllegalStateException。什麼都沒有承諾。EntityTransaction永不回滾,引發異常說事務處於未激活狀態

我有一個角色實體,它使用表生成策略爲此實體生成主鍵。無論何時提交失敗,並且下次我保存一個角色時,爲以前的保存生成的序列都會丟失,並且這次是遞增的。這個問題仍然存在於自動增量策略中。在使用hibernate SessionFactory的時候,我沒有遇到這個問題。

代碼:

Role.java

@Entity 
    @Table(schema="System") 
    public class Role extends PrincipalEntityBase{ 

    @TableGenerator(schema="System",table="MasterSequence", valueColumnName="Sequence", 
     pkColumnName="GenKey",pkColumnValue="Role_ID", 
     name="System.Role", allocationSize=0) 
@Id 
@GeneratedValue(generator="System.Role",strategy=GenerationType.TABLE) 
@Column(name="Role_ID") 
private Long role_ID; 

@Column(name="RoleName") 
private String roleName; 

    public Role() { 
    } 

public Long getRole_ID() { 
    return this.role_ID; 
} 

public void setRole_ID(Long role_ID) { 
    this.role_ID = role_ID; 
} 

public String getRoleName() { 
    return this.roleName; 
} 

public void setRoleName(String roleName) { 
    this.roleName = roleName; 
} 
} 

Main.java

public static void main(String[] args){ 
      Role r = new Role(); 
    r.setRoleName("Hello"); 
    EntityManager em = persistence.createEntityManagerFactory("test") 
      .createEntityManager(); 
    EntityTransaction tr = em.getTransaction(); 
    try { 
     tr.begin(); 
     em.persist(r); 
     tr.commit(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     tr.rollback(); 
     System.out.println("Rolled back"); 
    } 
    } 

堆棧跟蹤:

javax.persistence.RollbackException: Error while committing the transaction 
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:93) 
at com.mis.jpa.test.main.Main.main(Main.java:32) 
    Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not insert: [com.mis.entity.system.Role] 
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235) 
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168) 
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:81) 
... 1 more 
    Caused by: org.hibernate.exception.ConstraintViolationException: could not insert: [com.mis.entity.system.Role] 
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96) 
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) 

    Exception in thread "main" java.lang.IllegalStateException: Transaction not active 
at org.hibernate.ejb.TransactionImpl.rollback(TransactionImpl.java:104) 
at com.mis.jpa.test.main.Main.main(Main.java:35) 

DB服務器是MSSQL服務器。

的persistence.xml

<persistence-unit name="test" transaction-type="RESOURCE_LOCAL"> 
     <provider>org.hibernate.ejb.HibernatePersistence</provider> 

    <class>com.mis.entity.system.Role</class> 

    <properties> 

     <!-- Connection properties --> 
     <property name="javax.persistence.jdbc.driver" 
      value="com.microsoft.sqlserver.jdbc.SQLServerDriver" /> 
     <property name="javax.persistence.jdbc.url"    value="jdbc:sqlserver://192.168.1.2:1433;databaseName=jparesearch" /> 
     <property name="javax.persistence.jdbc.user" value="sa" /> 
     <property name="javax.persistence.jdbc.password" value="admin" /> 

     <!-- JPA Provider Settings --> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect" /> 
     <property name="hibernate.hbm2ddl.auto" value="update" /> 
     <property name="hibernate.show_sql" value="true" /> 
     </properties> 
</persistence-unit> 

回答

4

第一個問題:爲什麼回滾失敗。回滾失敗,因爲它不是在拋出異常的提交之前的某些代碼,而是提交本身。如果提交拋出一個RollbackException,那麼這意味着提交失敗了,並且因此將提交轉換爲回滾並使事務處於非活動狀態。只需在回滾事務之前測試事務是否處於活動狀態即可。

第二個問題:爲什麼生成的ID序列中有空洞。當生成器被要求提供新的ID時,會在其自己的短期交易中增加序列號。因此,如果您的事務回滾並因此不使用生成的ID,則序列中會有一個漏洞,因爲表中的增量已被提交。如果它沒有使用它自己的短期交易,那麼,要麼你會有很多衝突(因爲幾個長期交易會看到相同的當前價值,並且只會在稍後增加),否則吞吐量會很低,因爲所有需要ID的交易將不得不等待前一個交易完成。

孔是不可避免的。處理它們。

+0

非常感謝。如果序列上的回滾過度發生,那麼就是正確的,那麼就會出現性能問題,正如你所解釋的那樣。我從來沒有想過這方面。再次感謝。 – Megna

相關問題