Почему hibernate делает Выполнение идентификации-вставки немедленно - PullRequest
0 голосов
/ 25 декабря 2018

Когда я запускаю тест, я вижу в логах Executing identity-insert immediately Почему в спящем режиме сразу вставляют?Я ожидаю вставки во время коммита.

On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
begin
Executing identity-insert immediately

    /* insert MyJpaClass
        */ insert 
        into
            MyJpaClass
            (id, message) 
        values
            (null, ?)
Hibernate: 
    /* insert MyJpaClass
        */ insert 
        into
            MyJpaClass
            (id, message) 
        values
            (null, ?)
Natively generated identity: 1
HHH000387: ResultSet's statement was not registered
committing
Processing flush-time cascades
Dirty checking collections
Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
Listing entities:
MyJpaClass{id=1, message=text}
Initiating JDBC connection release from afterTransaction
Initiating JDBC connection release from afterTransaction

Это мой тестовый пример Persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
                                 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
  version="2.0">
<persistence-unit name="HelloWorldPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
        <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
        <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"/>
        <property name="javax.persistence.jdbc.user" value="sa"/>
        <property name="javax.persistence.jdbc.password" value=""/>

        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.format_sql" value="true"/>
        <property name="hibernate.use_sql_comments" value="true"/>
        <property name="hibernate.transaction.factory_class"
          value="org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory"/>
        <property name="hibernate.id.new_generator_mappings" value="true"/>
        <property name="hibernate.connection.autocommit" value="false"/>
        <property name="hibernate.hbm2ddl.auto" value="create-drop"/>

    </properties>
</persistence-unit>
</persistence>

Test

import static org.junit.Assert.assertNotNull;

import java.io.FileNotFoundException;
import java.sql.SQLException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class PersistTest {
    Logger LOG = LogManager.getLogger(PersistTest.class);

    protected static EntityManagerFactory emf;
    protected static EntityManager em;

    @BeforeClass
    public static void init() throws FileNotFoundException, SQLException {
        emf = Persistence.createEntityManagerFactory("HelloWorldPU");
        em = emf.createEntityManager();
    }

    @AfterClass
    public static void tearDown(){
        em.clear();
        em.close();
        emf.close();
    }

    @Test
    public void testPersist_success() {
        em.getTransaction().begin();
        MyJpaClass o = new MyJpaClass();
        o.setMessage("text");
        em.persist(o);
        em.getTransaction().commit();

        assertNotNull(o.getId());
        LOG.debug(o.getId());
    }
}

Entity

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class MyJpaClass {

    @Id
    @GeneratedValue (strategy= GenerationType.IDENTITY)
    private Long id;

    private String message;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

Поскольку вы используете GenerationType.IDENTITY, вставка выполняется напрямую, без ожидания фиксации, потому что вам нужно получить идентификатор.И чтобы получить идентификатор, вам нужно выполнить вставку в базе данных.

Вот почему GenerationType.SEQUENCE более эффективен, вставка может быть отложена, и вы можете включить пакетирование с помощью этой стратегии.

Больше информации о различных стратегиях: https://vladmihalcea.com/hibernate-identity-sequence-and-table-sequence-generator/

0 голосов
/ 25 декабря 2018

Слово immediately в Executing identity-insert immediately означает:

Требует ли контекст события доступа к идентификатору сразу после выполнения метода (если нет, отправьте-insert style генераторы идентификаторов могут быть отложены, если мы находимся за пределами транзакции).

Когда вы находитесь в транзакции, вам нужен идентификатор сразу после выполнения метода.Поэтому немедленно предоставьте его вам.

Когда вы сохраните базу вставки на своем уровне изоляции , вы можете иметь или не иметь доступ к данным в других сеансах.

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