Framework learning-Principles and analysis of transactions in Section 10 of Hibernate

Source: Internet
Author: User

1. Transactions

Two types of transactions:

① JDBC transaction: the transaction of a single database

A sesisonfactory corresponds to a database, implemented using JDBC

Templates for common code:

    Session session = null;    Transaction tx =null;    try {        session = sessionFactory.openSession();        tx = session.beginTransaction();        //process        tx.commit();    } catch(HibernateException e){        if(tx != null)tx.rollback();throw e;    }finally {        if (session != null)session.close();    }    connection.setAutoCommit(false);    connection.commit();conn.rollback();

 

② JTA transactions: Cross-database transactions

To use jtatransaction, you must configure the hibernate. transaction. factory_class parameter. The default value of this parameter is org. hibernate. transaction. jdbctransactionfactory,

When using jtatransaction, you must change this parameter to org. hibernate. transaction. jtatransactionfactory and configure the JTA. usertransaction parameter JNDI name.

[JNDI: Java Naming and Directory Interface, Java Naming and Directory Interface, is a group of APIS for accessing naming and directory services in Java applications.

The naming service associates the name with the object so that we can access the object with the name. Directory Service is a naming service in which objects not only have names but also attributes.]

(When starting jtatransaction, Hibernate uses this value to find javax. transaction. usertransaction in the context context of JNDI ).

Javax. transaction. usertranshyperlink Tx = context. Lookup ("jndiname ");

Javax. transaction. usertranshyperlink Tx = context. Lookup ("jndiname"); try {Tx. Begin (); // session operations for multiple databases; // session1 .... // Session2 .... TX. Commit ();} catch (exception e) {Tx. rollback (); throw E ;}

 

2. Open Session in view

Advantages: the data access layer and business logic layer are separated, and the three-layer architecture is better implemented.

Disadvantage: the session and transaction time is prolonged, which may cause insufficient memory or data lock.

Open session in view: Keep the session open when the page is generated (rendered.

Session Context and transaction boundary [Transaction boundary is transaction-related processing, including transaction opening, commit, and rollback]

Use the current_session_context_class attribute to define the context (use sessionfactory. getcurrentsession () to obtain the session). The value is:

1. Thread: threadlocal is used to manage sessions. Multiple operations share one session, avoiding repeated session acquisition and controlling the transaction boundary,

In this case, the session cannot be closed. When commit or rollback is used, the session is automatically closed (connection. release_mode: after_transaction ).

2. JTA: The JTA Transaction Manager manages transactions (connection. release_mode: after_statement ).

 

Test code: [NOTE: The following code is often stored in a J2EE project instead of j2se. Therefore, the following code will report an error when the javaee package is not introduced]

Package CN. itcast. hibernate; import Java. io. ioexception; import javax. servlet. filter; import javax. servlet. filterchain; import javax. servlet. filterconfig; import javax. servlet. servletexception; import javax. servlet. servletrequest; import javax. servlet. servletresponse; import Org. hibernate. session; import Org. hibernate. transaction; public class opensessioninview implements filter {public void destroy (){// Todo auto-generated method stub} public void dofilter (servletrequest arg0, servletresponse arg1, filterchain arg2) throws ioexception, servletexception {session = NULL; transaction Tx = NULL; try {session = hibernateutil. getthreadlocalsession (); Tx = session. begintransaction (); arg2.dofilter (arg0, arg1); // controls the transaction boundary to avoid getting sessions repeatedly. This ensures that the session is always Open Tx during transaction execution. commit ();} catch (exception E) {If (TX! = NULL) Tx. rollback (); throw new runtimeexception (E. getmessage (), e);} finally {hibernateutil. closesession () ;}} public void Init (filterconfig arg0) throws servletexception {// todo auto-generated method stub }}

 

Note: add the following content to hibernateutils:

    private static ThreadLocal session = new ThreadLocal();    public static Session getThreadLocalSession() {        Session s = (Session) session.get();        if (s == null) {            s = getSession();            session.set(s);        }        return s;    }        public static void closeSession() {        Session s = (Session) session.get();        if (s != null) {            s.close();            session.set(null);        }    }

Threadlocal is the current thread, through which the session object of the current thread can be obtained

 

3. pessimistic locks and optimistic locks in transactions

Problem: A and B open an editing page at the same time. Then a changes the original name to name1, submits the page, and saves it to the database.

Then B changed the original name, changed it to name2, submitted it, and saved it to the database. After two people's operations, A's operations have no effect, and B's operations are overwritten.

What's more, if they modify something different, B modifies the name and a modifies the content, then a's operations are all in vain.

Simply put, the sessions of two different threads operate on the same piece of data simultaneously and modify the data. The modified results are different, then, the submitted operations are valid operations.

Pessimistic locks are implemented by databases; optimistic locks are implemented by hibernate using version and timestamp.

Pessimistic lock: When a opens the edit, it will lock the data.

Disadvantage: After the lock is completed, other users cannot perform the operation. You must wait until a submits the operation.

Optimistic lock: adds a version number to the Data. Each time the data is updated, the version number is added. Hibernate implements Optimistic Locking. You only need to configure the version in the ing file.

Advantage: effectively prevents the above situation. if the version number of the submitted data is detected when the submission is earlier than the version number of the data in the database, the submission will fail.

In this case, whoever submits the job first will be successful! After submission, you can only open it again and modify it again.

Another optimistic lock implementation method is the timestamp. The type in version is timestamp, but there is a problem of time precision. It is better to use version (integer ).

Use version to test the Code:

First, add the version attribute to the people class and provide the get and set methods.

Then add the following in the people ing file: the integer method is used as an example.

<version name="version" type="integer"></version>

Finally, the test class: versiontest

Package COM. yinger. main; import Org. hibernate. session; import Org. hibernate. transaction; import COM. yinger. domain. name; import COM. yinger. domain. people; import COM. yinger. util. hibernateutils; public class versiontest {public static void main (string [] ARGs) {People P = addpeople (); system. out. println ("---------"); testtransaction (P. GETID (); system. out. println ("---------"); P = getpeople (P. GETID (); system. out. println (P. getname (). getfirstname ();} Private Static void testtransaction (int id) {session S1 = hibernateutils. getsession (); transaction tx1 = s1.begintransaction (); // a transaction has enabled people p1 = (people) s1.get (people. class, ID); Session S2 = hibernateutils. getsession (); transaction tx2 = s2.begintransaction (); // another transaction is started, and the same data entry is people P2 = (people) s2.get (people. class, ID); p2.getname (). setfirstname ("firstname 2"); p1.getname (). setfirstname ("firstname 1"); tx2.commit (); tx1.commit (); s1.close (); s2.close ();} public static people getpeople (int id) {People P = (people) hibernateutils. get (people. class, ID); Return P;} public static people addpeople () {People P = new people (); Name n = new name (); N. setfirstname ("firstname"); N. setlastname ("lastname"); p. setname (n); hibernateutils. add (p); Return P ;}}

Test results:

log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).log4j:WARN Please initialize the log4j system properly.Hibernate: insert into People (version, first_name, last_name, id) values (?, ?, ?, ?)---------Hibernate: update People set version=?, first_name=?, last_name=? where id=? and version=?Hibernate: update People set version=?, first_name=?, last_name=? where id=? and version=?Exception in thread "main" org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.yinger.domain.People#1]    at org.hibernate.persister.entity.BasicEntityPersister.check(BasicEntityPersister.java:1456)    at org.hibernate.persister.entity.BasicEntityPersister.update(BasicEntityPersister.java:1999)    at org.hibernate.persister.entity.BasicEntityPersister.updateOrInsert(BasicEntityPersister.java:1923)    at org.hibernate.persister.entity.BasicEntityPersister.update(BasicEntityPersister.java:2163)    at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:75)    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:239)    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:223)    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:137)    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:675)    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:293)    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)    at com.yinger.main.VersionTest.testTransaction(VersionTest.java:34)    at com.yinger.main.VersionTest.main(VersionTest.java:15)

 

Data in the database:

Id version first_name last_name

1 1 firstname 2 lastname

Change the order in which two transactions are committed and re-test

tx1.commit();tx2.commit();
Data in the database:

Id version first_name last_name

1 1 firstname 1 lastname

 
It can be seen from the results that: whoever submits the operation first is valid, and the latter cannot be submitted because the version number of the data operated by the user is lower than the version number of the data in the database.

This is the Optimistic Locking method to solve the above problems.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.