为了避免对对象同步操作时候产生的数据不一致问题,我们对对象采用加锁机制
悲观锁:从读取的时候开始加锁,直到修改完成。
缺点:读取完以后,用户修改过程缓慢,造成同步性降低。
乐观锁:给每条记录添加版本号,用来区别。两人同时编辑时候,假设获取的版本号都为1,编辑完提交的时候,版本号为2,
第一个提交完以后,数据库版本号为2,第二个提交的时候对比版本号就会报错。
解决的方法:在实体中加上版本号属性 在该映射文件中利用version节点配置其版本号,这样就可以由hibernate自己去维护
实体 部门
package vo.util.bean;
import java.util.Set;
/**
* 部门类
* @author Administrator
*
*/
public class Department {
private int id;
private String name;
private Set<Employee> ems;
//版本号
private int v;
public int getV() {
return v;
}
public void setV(int v) {
this.v = v;
}
public int getId() {
return id;
}
public Set<Employee> getEms() {
return ems;
}
public void setEms(Set<Employee> ems) {
this.ems = ems;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="vo.util.bean">
<class name="Department">
<id name="id">
<generator class="native"/>
</id>
<!-- 配置版本号 必须在id的下面来定义-->
<version name="v"/>
<property name="name"/>
<!-- 配置一对多的映射关系 -->
<set name="ems">
<!-- 关联关系的外键 -->
<key column="depaer_id"/>
<!-- 关联关系的实体类配置 -->
<one-to-many class="Employee" />
</set>
</class>
</hibernate-mapping>
测试
package vo.util.test;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;
import vo.util.HibernateUtil;
import vo.util.bean.Department;
import vo.util.bean.Employee;
public class VersonTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
add();
update(1);
}
static void update(int id)
{
Session s1=null;
Transaction tx1=null;
Session s2=null;
try {
Transaction tx2 = null;
s1 = HibernateUtil.getSession();
tx1 = s1.beginTransaction();
Department d1 = (Department) s1.get(Department.class, id);
s2 = HibernateUtil.getSession();
tx2 = s2.beginTransaction();
Department d2 = (Department) s2.get(Department.class, id);
d1.setName("new1");
d2.setName("new2");
tx2.commit();
tx1.commit();
} finally {
s1.close();
s2.close();
}
}
static Department add(){
Session session = null;
Transaction tx = null;
try{
session =HibernateUtil.getSession();
tx = session.beginTransaction();
//…你的代码save,delete,update,get…
Department dpart=new Department();
dpart.setName("政企事业部");
//dpart.setVar(1);
Employee em1=new Employee();
em1.setName("员工李小仙");
//em1.setDerpartment(dpart);
Employee em2=new Employee();
em2.setName("员工张小三");
//em2.setDerpartment(dpart);
Set<Employee> em=new HashSet<Employee>();
em.add(em1);
em.add(em2);
dpart.setEms(em);
session.save(dpart);
session.save(em1);
session.save(em2);
tx.commit();
return dpart;
}finally{
if(session != null)session.close();
}
}
}
运行测试
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
打开连接成功!Hibernate: insert into Department (v, name) values (?, ?)
Hibernate: insert into Employee (name, depaer_id) values (?, ?)
Hibernate: insert into Employee (name, depaer_id) values (?, ?)
Hibernate: update Employee set depaer_id=? where id=?
Hibernate: update Employee set depaer_id=? where id=?
Hibernate: select department0_.id as id0_0_, department0_.v as v0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?
Hibernate: select department0_.id as id0_0_, department0_.v as v0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?
Hibernate: update Department set v=?, name=? where id=? and v=?
Hibernate: update Department set v=?, name=? where id=? and v=?
Exception in thread "main" org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [vo.util.bean.Department#1]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1765)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2407)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2307)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2607)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at vo.util.test.VersonTest.update(VersonTest.java:41)
at vo.util.test.VersonTest.main(VersonTest.java:21)
分析:第一次更新语句下没报异常,第二次更新就报异常了,这是因为版本号不一致,已经修改了的问题 这是不
是解决了同步修改的问题呢?
完毕 end!