zoukankan      html  css  js  c++  java
  • Hibernate:有了 save,为什么还需要 persist?

    背景

    万物皆自然,每个 API 的设计,无论是否正确,都有其意图。因此,在学习某些框架的时候,我们需要经常思考:这个 API 的设计意图是啥?

    本文来探讨一下 Session 中 persist 的设计意图。

    官方注释

    save

     1     /**
     2      * Persist the given transient instance, first assigning a generated identifier. (Or
     3      * using the current value of the identifier property if the <tt>assigned</tt>
     4      * generator is used.) This operation cascades to associated instances if the
     5      * association is mapped with {@code cascade="save-update"}
     6      *
     7      * @param object a transient instance of a persistent class
     8      *
     9      * @return the generated identifier
    10      */
    11     public Serializable save(Object object);

    persist

    1     /**
    2      * Make a transient instance persistent. This operation cascades to associated
    3      * instances if the association is mapped with {@code cascade="persist"}
    4      * <p/>
    5      * The semantics of this method are defined by JSR-220.
    6      *
    7      * @param object a transient instance to be made persistent
    8      */
    9     public void persist(Object object);

    解释

    save 因为需要返回一个主键值,因此会立即执行 insert 语句,而 persist 在事务外部调用时则不会立即执行 insert 语句,在事务内调用还是会立即执行 insert 语句的。

    看 persist 的注释会觉得其不会立即执行 insert 语句,为何 在事务内调用会立即执行 insert 语句,后面再分析。

    测试

    SessionHelper

     1 package demo;
     2 
     3 import org.hibernate.*;
     4 import org.hibernate.cfg.*;
     5 
     6 public final class SessionHelper {
     7     private static SessionFactory factory;
     8 
     9     public static void execute(SessionAction action) {
    10         execute(action, false);
    11     }
    12 
    13     public static void execute(SessionAction action, boolean beforeTransaction) {
    14         Session session = openSession();
    15         try {
    16             if (beforeTransaction) {
    17                 System.out.println("action");
    18                 action.action(session);
    19             }
    20 
    21             System.out.println("begin transaction");
    22             session.beginTransaction();
    23             if (!beforeTransaction) {
    24                 System.out.println("action");
    25                 action.action(session);
    26             }
    27 
    28             System.out.println("flush and commit");
    29             session.flush();
    30             session.getTransaction().commit();
    31         } catch (Exception ex) {
    32             session.getTransaction().rollback();
    33         } finally {
    34             session.close();
    35         }
    36     }
    37 
    38     @SuppressWarnings("deprecation")
    39     public static Session openSession() {
    40         if (factory == null) {
    41             factory = new Configuration().configure().buildSessionFactory();
    42         }
    43 
    44         return factory.openSession();
    45     }
    46 }

    save

     1 package demo;
     2 
     3 import model.*;
     4 
     5 import org.hibernate.*;
     6 /*
     7  * save 会导致 insert 语句的立即执行。
     8  */
     9 public class SaveDemo implements Demo {
    10 
    11     @Override
    12     public void run() {
    13         SessionHelper.execute(new SessionAction() {
    14 
    15             @Override
    16             public void action(Session session) {
    17                 User user = new User();
    18                 user.setUsername("woshishui");
    19                 user.setPassword("123456");
    20 
    21                 session.save(user);
    22             }
    23 
    24         });
    25     }
    26 
    27 }

    输出结果

     1 begin transaction
     2 action
     3 Hibernate: 
     4     /* insert model.User
     5         */ insert 
     6         into
     7             USERS
     8             (USERNAME, PASSWORD) 
     9         values
    10             (?, ?)
    11 flush and commit

    persis in transactiont

     1 package demo;
     2 
     3 import model.*;
     4 
     5 import org.hibernate.*;
     6 
     7 /*
     8  * persist 在事务中执行,会导致 insert 语句的立即执行。
     9  */
    10 public class PersisInTransactiontDemo implements Demo {
    11 
    12     @Override
    13     public void run() {
    14         SessionHelper.execute(new SessionAction() {
    15 
    16             @Override
    17             public void action(Session session) {
    18                 User user = new User();
    19                 user.setUsername("woshishui");
    20                 user.setPassword("123456");
    21 
    22                 session.persist(user);
    23             }
    24 
    25         });
    26     }
    27 
    28 }

    输出结果

     1 begin transaction
     2 action
     3 Hibernate: 
     4     /* insert model.User
     5         */ insert 
     6         into
     7             USERS
     8             (USERNAME, PASSWORD) 
     9         values
    10             (?, ?)
    11 flush and commit

    persis before transactiont

     1 package demo;
     2 
     3 import model.*;
     4 
     5 import org.hibernate.*;
     6 
     7 /*
     8  * persist 不在事务中执行,不会导致 insert 语句的立即执行,而是在 flush 时执行 insert 语句。
     9  */
    10 public class PersisBeforeTransactiontDemo implements Demo {
    11 
    12     @Override
    13     public void run() {
    14         SessionHelper.execute(new SessionAction() {
    15 
    16             @Override
    17             public void action(Session session) {
    18                 User user = new User();
    19                 user.setUsername("woshishui");
    20                 user.setPassword("123456");
    21 
    22                 session.persist(user);
    23             }
    24 
    25         }, true);
    26     }
    27 
    28 }

    输出结果

     1 action
     2 begin transaction
     3 flush and commit
     4 Hibernate: 
     5     /* insert model.User
     6         */ insert 
     7         into
     8             USERS
     9             (USERNAME, PASSWORD) 
    10         values
    11             (?, ?)

    分析

    为何 persist 在事务内和事务外表现的行为不同呢?为何这样设计?目前还没有查到官方的第一手资料(刚学习 Java 和 Hibernate),我的猜测是:事务外的 persist 是为了应对长事务,事务内的 persist 是为了和 save 保持一个语义

    备注

    学习 Hibernate 的过程也相当于从新学习了一遍 EntityFramework,换个视角总有好处。

  • 相关阅读:
    我罗斯方块
    《程序设计语言综合设计》第四周上机练习——5 好吃的巧克力
    《程序设计语言综合设计》第四周上机练习——4 特殊的翻译
    《程序设计语言综合设计》第四周上机练习——3 开机方案
    《程序设计语言综合设计》第三周上机练习——3 不诚实的卖家
    《高级语言程序设计实践》期末考试复现——9 丢手绢
    《高级语言程序设计实践》期末考试复现——7 芽衣的厨房
    《高级语言程序设计实践》期末考试复现——5 圣诞老人的糖果
    《高级语言程序设计实践》期末考试复现——4 希儿的日记本
    FZU_DS_2019_SequenceList
  • 原文地址:https://www.cnblogs.com/happyframework/p/3352158.html
Copyright © 2011-2022 走看看