悲观锁 就是读写时都加锁
package hibernate_manytomany;
import java.util.Date;
import org.hibernate.LockMode;
import org.hibernate.Session;
import hibernate.belle.Inventory;
import hibernate.belle.FiscalPK;
import hibernate.belle.HibernateUtils;
import junit.framework.TestCase;
public class Extends extends TestCase{
public void teststore(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
Inventory inv=new Inventory();
inv.setItemno(1001);
inv.setName("zara");
inv.setQuantity(100);
session.save(inv);
session.beginTransaction().commit();
}catch(Exception e)
{
e.printStackTrace();
session.beginTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
public void testrevise1(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
Inventory inv=(Inventory)session.load(Inventory.class, 1001,LockMode.UPGRADE);
inv.setQuantity(inv.getQuantity()-20);
System.out.println("quantity="+inv.getQuantity());
session.beginTransaction().commit();
}catch(Exception e)
{
e.printStackTrace();
session.beginTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
public void testrevise2(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
Inventory inv=(Inventory)session.load(Inventory.class, 1001,LockMode.UPDATE);
inv.setQuantity(inv.getQuantity()-20);
System.out.println("2=="+inv.getQuantity());
session.beginTransaction().commit();
}catch(Exception e)
{
e.printStackTrace();
session.beginTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
}
当我对1单步调试 不释放的时候 直接run2 会报错
Hibernate:
select
inventory0_.Itemno as Itemno0_0_,
inventory0_.name as name0_0_,
inventory0_.quantity as quantity0_0_
from
t_inv inventory0_
where
inventory0_.Itemno=? for update
20:37:27,356 WARN JDBCExceptionReporter:77 - SQL Error: 1205, SQLState: 41000
20:37:27,359 ERROR JDBCExceptionReporter:78 - Lock wait timeout exceeded; try restarting transaction
org.hibernate.exception.GenericJDBCException: could not load an entity: [hibernate.belle.Inventory#1001]
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1865)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3038)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:395)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:375)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)
at org.hibernate.event.def.DefaultLoadEventListener.lockAndLoad(DefaultLoadEventListener.java:297)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:106)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
at org.hibernate.impl.SessionImpl.load(SessionImpl.java:859)
at org.hibernate.impl.SessionImpl.load(SessionImpl.java:854)
at hibernate_manytomany.Extends.testrevise1(Extends.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:131)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3603)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3535)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1989)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2150)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2626)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2119)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2281)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:186)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1778)
at org.hibernate.loader.Loader.doQuery(Loader.java:662)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1851)
... 28 more
乐观锁
package hibernate.belle;
import java.util.Date;
public class Inventory {
private int itemno;
private int quantity;
private String name;
private int version;
public int getItemno() {
return itemno;
}
public void setItemno(int itemno) {
this.itemno = itemno;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping >
<class name="hibernate.belle.Inventory" table="t_inv" optimistic-lock="version">
<id name="Itemno">
<generator class="assigned"></generator>
</id>
<version name="version"/>
<property name="name"></property>
<property name="quantity"></property>
</class>
</hibernate-mapping>
package hibernate_manytomany;
import java.util.Date;
import org.hibernate.LockMode;
import org.hibernate.Session;
import hibernate.belle.Inventory;
import hibernate.belle.FiscalPK;
import hibernate.belle.HibernateUtils;
import junit.framework.TestCase;
public class Extends extends TestCase{
public void teststore(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
Inventory inv=new Inventory();
inv.setItemno(1001);
inv.setName("zara");
inv.setQuantity(100);
session.save(inv);
session.beginTransaction().commit();
}catch(Exception e)
{
e.printStackTrace();
session.beginTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
public void testrevise1(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
Inventory inv=(Inventory)session.load(Inventory.class, 1001);
inv.setQuantity(inv.getQuantity()-20);
System.out.println("revise1"+inv.getVersion());
System.out.println("quantity="+inv.getQuantity());
session.beginTransaction().commit();
}catch(Exception e)
{
e.printStackTrace();
session.beginTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
public void testrevise2(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
Inventory inv=(Inventory)session.load(Inventory.class, 1001);
inv.setQuantity(inv.getQuantity()-20);
System.out.println("revise2"+inv.getVersion());
System.out.println("quantity="+inv.getQuantity());
session.beginTransaction().commit();
}catch(Exception e)
{
e.printStackTrace();
session.beginTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
}
同上 1先占着锁 不释放 然后2直接run 报错 因为 此时数据库里查到的version是1 与1现在所持有的version0 不匹配 报一下错
20:56:22,810 ERROR AbstractFlushingEventListener:301 - Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)