EntityTransaction никогда не откатывается, выдает исключение, сообщающее, что транзакция не активна - PullRequest
0 голосов
/ 18 ноября 2011

Я работаю над автономным приложением java, использующим JPA для сохранения объектов, и провайдер Hibernate.Теперь, когда я сохраняю сущность и вызываю commit () из EntityTransaction, сущность сохраняется в базе данных.Если в ограничениях и т. Д. Есть ошибка базы данных, возникает исключение, и при попытке отката я получаю исключение java.lang.IllegalStateException.Ничего не совершается.

У меня есть объект Role, который использует стратегию генерации таблицы для генерации первичного ключа для этого объекта.Всякий раз, когда фиксация завершается неудачей, и в следующий раз, когда я сохраняю роль, последовательность, сгенерированная для предыдущего сохранения, теряется, и на этот раз она увеличивается.Эта проблема сохраняется и для стратегии автоматического увеличения.Я не сталкивался с этой проблемой при работе с 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");
    }
    }

StackTrace:

    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>

1 Ответ

4 голосов
/ 18 ноября 2011

Первый вопрос: почему не удается выполнить откат.Откат завершается неудачей, потому что это не какой-то код перед коммитом, который выдал исключение, а сам коммит.Если commit генерирует RollbackException, то это означает, что фиксация завершилась неудачно и, таким образом, преобразовала фиксацию в откат и сделала транзакцию неактивной.Просто проверьте, активна ли транзакция, прежде чем откатывать транзакцию.

Второй вопрос: почему в последовательности сгенерированных идентификаторов есть дыры.При запросе нового идентификатора генератор увеличивает порядковый номер в своей собственной краткосрочной транзакции.Таким образом, если ваша транзакция откатывается и, следовательно, не использует сгенерированный идентификатор, в последовательности будет дыра, поскольку приращение в таблице уже зафиксировано.Если бы он не использовал свою собственную недолговечную транзакцию, то у вас было бы много конфликтов (потому что несколько длинных транзакций увидели бы одно и то же текущее значение и только увеличили бы его позже), или пропускная способность была бы очень низкой, потому что всетранзакции, для которых требуется идентификатор, должны будут ждать завершения предыдущей транзакции.

Отверстия неизбежны.Разобраться с ними.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...