Hibernate中樂觀鎖的實現(xiàn)示例
Hibernate的樂觀鎖(Optimistic Locking)是一種并發(fā)控制機(jī)制,用于防止在多個事務(wù)并發(fā)訪問相同數(shù)據(jù)時出現(xiàn)數(shù)據(jù)沖突。樂觀鎖的基本思想是,每次讀取數(shù)據(jù)時不進(jìn)行實際的加鎖操作,而是在提交更新時檢查數(shù)據(jù)是否已經(jīng)被其他事務(wù)修改。如果數(shù)據(jù)在此期間被其他事務(wù)修改,則當(dāng)前事務(wù)會回滾并重新嘗試。
樂觀鎖的實現(xiàn)
樂觀鎖通常通過版本號(version)字段實現(xiàn)。每次更新數(shù)據(jù)時,都會檢查版本號是否一致,并將版本號加1。
示例代碼
下面是一個完整的示例,展示如何在Hibernate中使用樂觀鎖。
配置文件hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 數(shù)據(jù)庫連接配置 -->
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/your_database</property>
<property name="hibernate.connection.username">your_username</property>
<property name="hibernate.connection.password">your_password</property>
<!-- Hibernate 屬性配置 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 映射類配置 -->
<mapping class="com.example.domain.Student"/>
</session-factory>
</hibernate-configuration>
HibernateUtil 類
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
// 從配置文件創(chuàng)建SessionFactory
sessionFactory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
} catch (Throwable ex) {
// 記錄啟動失敗的錯誤
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
實體類 Student
package com.example.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Version;
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
@Version
private int version;
public Student() {}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// getters 和 setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
}
樂觀鎖示例代碼
下面的示例展示了如何在并發(fā)環(huán)境中使用樂觀鎖。
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
public class HibernateOptimisticLockingExample {
public static void main(String[] args) {
// 獲取SessionFactory
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
// 第一個會話
Session session1 = sessionFactory.openSession();
Transaction transaction1 = session1.beginTransaction();
// 第二個會話
Session session2 = sessionFactory.openSession();
Transaction transaction2 = session2.beginTransaction();
try {
// 在第一個會話中獲取對象
Student student1 = session1.get(Student.class, 1L);
System.out.println("Session1 - Student: " + student1.getName() + ", Age: " + student1.getAge() + ", Version: " + student1.getVersion());
// 在第二個會話中獲取相同的對象
Student student2 = session2.get(Student.class, 1L);
System.out.println("Session2 - Student: " + student2.getName() + ", Age: " + student2.getAge() + ", Version: " + student2.getVersion());
// 修改并更新對象
student1.setAge(21);
session1.update(student1);
transaction1.commit();
System.out.println("Session1 - Updated Student: " + student1.getName() + ", Age: " + student1.getAge() + ", Version: " + student1.getVersion());
// 嘗試在第二個會話中提交修改
student2.setAge(22);
session2.update(student2);
transaction2.commit(); // 這里會拋出異常,因為版本號不一致
} catch (Exception e) {
if (transaction2 != null) {
transaction2.rollback();
}
e.printStackTrace();
} finally {
if (session1 != null) {
session1.close();
}
if (session2 != null) {
session2.close();
}
}
// 關(guān)閉SessionFactory
sessionFactory.close();
}
}
詳細(xì)解釋
配置樂觀鎖:在實體類中添加一個
@Version注解的字段,通常為整數(shù)類型。@Version private int version;
示例場景:
- 在第一個會話中獲取同一個Student對象,修改其屬性并提交更新。
- 在第二個會話中獲取同一個Student對象,也修改其屬性并試圖提交更新。
- 由于版本號不一致,第二個會話在提交更新時會拋出異常(
org.hibernate.StaleObjectStateException)。
事務(wù)管理:在事務(wù)中進(jìn)行數(shù)據(jù)操作,并在操作完成后提交事務(wù)。如果操作失敗,則回滾事務(wù)以確保數(shù)據(jù)一致性。
總結(jié)
樂觀鎖是一種有效的并發(fā)控制機(jī)制,通過版本號字段可以防止多個事務(wù)并發(fā)修改相同數(shù)據(jù)時出現(xiàn)數(shù)據(jù)沖突。在Hibernate中,通過@Version注解可以非常方便地實現(xiàn)樂觀鎖。理解并正確應(yīng)用樂觀鎖,可以有效地提高應(yīng)用的并發(fā)處理能力和數(shù)據(jù)一致性。
到此這篇關(guān)于Hibernate中樂觀鎖的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)Hibernate 樂觀鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
部署springboot項目到云服務(wù)器的兩種方式(jar+war)
本文主要介紹了部署springboot項目到云服務(wù)器的兩種方式,主要介紹了jar和war兩種方式,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12
Java中的System類、BigInteger類和BigDecimal類詳解
這篇文章主要介紹了Java中的System類、BigInteger類和BigDecimal類詳解,arraycopy()方法,復(fù)制數(shù)組元素,比較適合底層調(diào)用,一般使用Arrays.copyOf()完成復(fù)制數(shù)組,需要的朋友可以參考下2023-09-09
解決Springboot獲取不到nacos配置中心的配置問題
由于項目使用的nacos老版本,存在風(fēng)險bug, 需要將nacos升級至2.2.1及以上版本,版本升級完畢之后 啟動項目發(fā)現(xiàn)項目開始報錯,所以本文記錄一下Springboot獲取不到nacos配置中心的配置問題,文中有詳細(xì)的解決方法,需要的朋友可以參考下2023-09-09
Springboot jar包 idea 遠(yuǎn)程調(diào)試的操作過程

