Jpa EntityTransaction从不回滚,抛出异常,表示事务未处于活动状态

Jpa EntityTransaction从不回滚,抛出异常,表示事务未处于活动状态,jpa,Jpa,我正在开发一个独立的java应用程序,使用JPA进行对象持久化,提供程序是Hibernate。现在,当我持久化一个实体并调用EntityTransaction的commit()时,该实体将持久化到数据库中。如果约束等出现数据库错误,则会出现异常,当我尝试回滚时,会得到一个java.lang.IllegalStateException。什么都不会犯 我有一个角色实体,它使用表生成策略为该实体生成主键。每当提交失败并且下次保存角色时,为上一次保存生成的序列将丢失,而这次是递增序列。对于自动增量策略,

我正在开发一个独立的java应用程序,使用JPA进行对象持久化,提供程序是Hibernate。现在,当我持久化一个实体并调用EntityTransaction的commit()时,该实体将持久化到数据库中。如果约束等出现数据库错误,则会出现异常,当我尝试回滚时,会得到一个java.lang.IllegalStateException。什么都不会犯

我有一个角色实体,它使用表生成策略为该实体生成主键。每当提交失败并且下次保存角色时,为上一次保存生成的序列将丢失,而这次是递增序列。对于自动增量策略,这个问题仍然存在。在使用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)
数据库服务器是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>

org.hibernate.ejb.HibernatePersistence
com.mis.entity.system.Role

第一个问题:为什么回滚失败。回滚失败,因为引发异常的不是提交之前的某个代码,而是提交本身。如果提交引发回滚异常,则表示提交失败,因此将提交转换为回滚并使事务处于非活动状态。在回滚事务之前,只需测试事务是否处于活动状态

第二个问题:为什么生成的ID序列中存在漏洞。当要求生成器提供新ID时,生成器会在其自己的短期事务中增加序列号。因此,如果事务回滚,因此不使用生成的ID,那么序列中将有一个漏洞,因为表中的增量已经提交。如果它不使用自己的短命事务,那么,要么会有很多冲突(因为几个长事务会看到相同的当前值,只是在以后增加),要么吞吐量会非常低,因为所有需要ID的事务都必须等待前一个事务完成


洞是不可避免的。处理它们。

第一个问题:为什么回滚失败。回滚失败,因为引发异常的不是提交之前的某个代码,而是提交本身。如果提交引发回滚异常,则表示提交失败,因此将提交转换为回滚并使事务处于非活动状态。在回滚事务之前,只需测试事务是否处于活动状态

第二个问题:为什么生成的ID序列中存在漏洞。当要求生成器提供新ID时,生成器会在其自己的短期事务中增加序列号。因此,如果事务回滚,因此不使用生成的ID,那么序列中将有一个漏洞,因为表中的增量已经提交。如果它不使用自己的短命事务,那么,要么会有很多冲突(因为几个长事务会看到相同的当前值,只是在以后增加),要么吞吐量会非常低,因为所有需要ID的事务都必须等待前一个事务完成


洞是不可避免的。处理好它们。

非常感谢。您是对的,如果序列上的回滚也发生了,那么正如您所解释的,将出现性能问题。我从来没有想过这方面。再次感谢,非常感谢。您是对的,如果序列上的回滚也发生了,那么正如您所解释的,将出现性能问题。我从来没有想过这方面。再次感谢。