代码之家  ›  专栏  ›  技术社区  ›  aggredi

为什么hibernate要立即执行identity insert

  •  1
  • aggredi  · 技术社区  · 7 年前

    当我运行测试时,我在日志中看到 Executing identity-insert immediately 为什么hibernate运行立即插入?我希望在提交时插入。

    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
    

    这是我的测试示例 持久性.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>
    

    试验

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

    实体

    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 回复  |  直到 7 年前
        1
  •  0
  •   Mohsen    7 年前

    单词 immediately Executing identity-insert immediately 手段:

    事件上下文是否要求访问标识符 立即 方法执行后(如果没有,则为插入后样式id 如果我们不在交易范围内,发电机可能会推迟。

    当您在事务中时,您需要在方法执行后立即使用标识符。所以马上提供给你。

    当您在 isolation level 您可以在其他会话中访问或不访问其他会话中的数据。

        2
  •  0
  •   Reda    7 年前

    因为您使用generationtype.identity,所以直接执行插入而不等待提交,因为您需要获取id。为了获取id,您必须在数据库中执行插入。

    这就是为什么GuangyType。序列更高效,插入可以推迟,并且可以使用这种策略进行批量处理。

    有关不同策略的更多信息: https://vladmihalcea.com/hibernate-identity-sequence-and-table-sequence-generator/