Spring 事务管理器的原理是假设我们运行对数据库进行各种操作需要同步,也就是不写入脏数据进入我们系统里面,然而一般的事物管理器需要很多冗余的代码控制,所以spring帮助我们完成这个操作。也就是我们事务代理机制。其将代理控制在service层进行统一控制。然后我们每次访问service看似访问我们的接口实现类,但是实际上是访问我们的spring事务代理接口,然后由我们代理统一来调用service方法。如果成功就写入数据,不成功就完全回滚。
基本的思路就是如下:
然后就是在spring配置文件进行如下更改:
<!-- spring 声明式事务配置 --> <bean id="studentService" parent="hibernateTxProxyTemplate"> <property name="target" ref="studentServiceTarget"></property> </bean> <bean id="studentServiceTarget" class="edu.fjnu.training.service.StudentServiceImpl"> <property name="studentDao" ref="studentDao"></property> <property name="clazzDao" ref="clazzDao"></property> </bean>
下面看一下基本的spring配置文件:
至于其他的实现类我们不需要进行修改。
但是如果我们在原来的类方法中如果定义了事务管理器的话,我们需要进行将这些事物管理注释掉,统一用我们的spring事务管理代替。
然后由于我们采用了spring事务管理器,我们的原来的有些代码dao层代码可能会出现一些问题。这个就需要根据情况而定了。当然也不是什么大问题,例如:更新的话我们改成:
/**没用事务管理器之前,我们用update,但是在我们用事务管理器之后,我们习惯性用merge*/ // this.getHibernateTemplate().update(stu); this.getHibernateTemplate().merge(stu);
但是基本上其他的不用变化太大。然后下面就是一些基本发生变化的地方:贴下代码如下:
我们对于spring配置文件可以份文件处理;也就是由原来的一个变成多个文件管理,方便更改管理。
applicationContext-common.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd" [ <!ENTITY contextInclude SYSTEM "org/springframework/web/portlet/context/WEB-INF/contextInclude.xml"> ]> <beans> <!-- ====================================== --> <!-- ClazzAction对象 --> <bean id="clazzAction" class="edu.fjnu.training.action.ClazzAction" scope="prototype"> <property name="clazzService" ref="clazzService"></property> </bean> <!-- --> <bean id="clazzService" parent="hibernateTxProxyTemplate"> <property name="target" ref="clazzServiceTarget"></property> </bean> <!-- ClazzService对象 --> <bean id="clazzServiceTarget" class="edu.fjnu.training.service.ClazzServiceImpl"> <property name="clazzDao" ref="clazzDao"></property> </bean> <!-- ClazzDao对象 --> <bean id="clazzDao" class="edu.fjnu.training.dao.ClazzDaoHibernateImpl"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> </beans>
applicationContext-clazz.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd" [ <!ENTITY contextInclude SYSTEM "org/springframework/web/portlet/context/WEB-INF/contextInclude.xml"> ]> <beans> <!-- ====================================== --> <!-- ClazzAction对象 --> <bean id="clazzAction" class="edu.fjnu.training.action.ClazzAction" scope="prototype"> <property name="clazzService" ref="clazzService"></property> </bean> <!-- --> <bean id="clazzService" parent="hibernateTxProxyTemplate"> <property name="target" ref="clazzServiceTarget"></property> </bean> <!-- ClazzService对象 --> <bean id="clazzServiceTarget" class="edu.fjnu.training.service.ClazzServiceImpl"> <property name="clazzDao" ref="clazzDao"></property> </bean> <!-- ClazzDao对象 --> <bean id="clazzDao" class="edu.fjnu.training.dao.ClazzDaoHibernateImpl"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> </beans>
applicationContext-user.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd" [ <!ENTITY contextInclude SYSTEM "org/springframework/web/portlet/context/WEB-INF/contextInclude.xml"> ]> <beans> <!-- ====================================== --> <!-- 安全登录SecurityAction对象 scope="prototype" 表示这个Action--> <bean id="securityAction" class="edu.fjnu.training.action.SecurityAction" scope="prototype"> <property name="userService" ref="userService"></property> </bean> <!-- --> <bean id="userService" parent="hibernateTxProxyTemplate"> <property name="target" ref="userServiceTarget"></property> </bean> <!-- UserService对象服务 --> <bean id="userServiceTarget" class="edu.fjnu.training.service.UserServiceImpl"> <property name="userDao" ref="userDao"></property> </bean> <!-- UserDao对象 --> <bean id="userDao" class="edu.fjnu.training.dao.UserDaoHibernateImpl"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> </beans>
applicationContext-student.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd" [ <!ENTITY contextInclude SYSTEM "org/springframework/web/portlet/context/WEB-INF/contextInclude.xml"> ]> <beans> <!-- ====================================== --> <bean id="studentAction" class="edu.fjnu.training.action.StudentAction" scope="prototype"> <property name="studentService" ref="studentService"></property> <property name="clazzService" ref="clazzService"></property> </bean> <!-- spring 声明式事务配置 --> <bean id="studentService" parent="hibernateTxProxyTemplate"> <property name="target" ref="studentServiceTarget"></property> </bean> <bean id="studentServiceTarget" class="edu.fjnu.training.service.StudentServiceImpl"> <property name="studentDao" ref="studentDao"></property> <property name="clazzDao" ref="clazzDao"></property> </bean> <bean id="studentDao" class="edu.fjnu.training.dao.StudentDaoHibernateImpl"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> </beans>
Dao层文件的修改:
StudentDaoHibernateImpl.java
/** * 工 程 名:SMS-SSH-20180524 <br> * 文 件 名:StudentDaoHibernateImpl.java <br> * 工具包名:edu.fjnu.training.dao <br> * 功能描述:TODO <br> * 创建时间:2018年5月26日 下午8:28:07 <br> * 版本信息:V1.0 * @创建人:Zhou Kailun */ package edu.fjnu.training.dao; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Order; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import edu.fjnu.training.domain.Student; import edu.fjnu.training.service.StudentQueryHelper; import edu.fjnu.training.utils.HibernateUtils; /** * 类名:StudentDaoHibernateImpl <br> * 功能描述: <br> * 创建日期:2018年5月26日 下午8:28:07 <br> * 修改备注: * @作者信息:Zhou kailun <br> */ public class StudentDaoHibernateImpl extends HibernateDaoSupport implements StudentDao { /**<p>构造函数:</p><br><br> * <p>描述:</p><br> */ public StudentDaoHibernateImpl() { // TODO Auto-generated constructor stub } /* (非 Javadoc) * <p>Title:addStudent</p> * <p>描 述:</p> * @param stu * @see edu.fjnu.training.dao.StudentDao#addStudent(edu.fjnu.training.domain.Student) */ @Override public void addStudent(Student stu) { // Session session=HibernateUtils.createSession(); // Transaction trans=null; // trans=session.beginTransaction();; // try{ // session.saveOrUpdate(stu); // trans.commit(); // }catch(HibernateException e){ // e.printStackTrace(); // trans.rollback(); // }finally{ // if(session.isOpen()){ // session.close(); // } // } this.getHibernateTemplate().save(stu); } /* (非 Javadoc) * <p>Title:removeStudent</p> * <p>描 述:</p> * @param stuNo * @see edu.fjnu.training.dao.StudentDao#removeStudent(java.lang.String) */ @Override public void removeStudent(String stuNo) { // Session session=HibernateUtils.createSession(); // Transaction trans=null; // trans=session.beginTransaction();; // try{ // Student stu=(Student)session.load(Student.class, stuNo); // // session.delete(stu); // trans.commit(); // }catch(HibernateException e){ // e.printStackTrace(); // trans.rollback(); // }finally{ // if(session.isOpen()){ // session.close(); // } // } Student stu = (Student)this.getHibernateTemplate().load(Student.class, stuNo); this.getHibernateTemplate().delete(stu); } /* (非 Javadoc) * <p>Title:loadAllStudent</p> * <p>描 述:</p> * @return * @see edu.fjnu.training.dao.StudentDao#loadAllStudent() */ @Override public List<Student> loadAllStudent() { String hql="from Student s order by s.stuNo desc";//查询语句 // Session session=HibernateUtils.createSession(); // Transaction trans=null; // List<Student> stuList=null; // // trans=session.beginTransaction(); // try{ // // stuList=session.createQuery(hql).list(); // trans.commit(); // }catch(HibernateException e){ // e.printStackTrace(); // trans.rollback(); // }finally{ // if(session.isOpen()){ // session.close(); // } // } // return stuList; return this.getHibernateTemplate().find(hql); } /* (非 Javadoc) * <p>Title:getStudentByStuNo</p> * <p>描 述:</p> * @param stuNo * @return * @see edu.fjnu.training.dao.StudentDao#getStudentByStuNo(java.lang.String) */ @Override public Student getStudentByStuNo(String stuNo) { // Session session=HibernateUtils.createSession(); // Transaction trans=null; // Student stu=null; // // trans=session.beginTransaction(); // try{ // stu=(Student)session.get(Student.class, stuNo); // trans.commit(); // }catch(HibernateException e){ // e.printStackTrace(); // trans.rollback(); // }finally{ // if(session.isOpen()){ // session.close(); // } // } // return stu; return (Student)this.getHibernateTemplate().get(Student.class, stuNo); } /* (非 Javadoc) * <p>Title:updateStudent</p> * <p>描 述:</p> * @param stu * @see edu.fjnu.training.dao.StudentDao#updateStudent(edu.fjnu.training.domain.Student) */ @Override public void updateStudent(Student stu) { if(stu.getStuPic()==null || stu.getStuPic().length==0){ stu.setStuPic(this.loadStuPicByNo(stu.getStuNo())); } // // Session session=HibernateUtils.createSession(); // Transaction trans=null; // // trans=session.beginTransaction(); // try{ // session.saveOrUpdate(stu);; // trans.commit(); // }catch(HibernateException e){ // e.printStackTrace(); // trans.rollback(); // }finally{ // if(session.isOpen()){ // session.close(); // } // } /**没用事务管理器之前,我们用update,但是在我们用事务管理器之后,我们习惯性用merge*/ // this.getHibernateTemplate().update(stu); this.getHibernateTemplate().merge(stu); } /* (非 Javadoc) * <p>Title:loadStuPicByNo</p> * <p>描 述:</p> * @param stuNo * @return * @see edu.fjnu.training.dao.StudentDao#loadStuPicByNo(java.lang.String) */ @Override public byte[] loadStuPicByNo(String stuNo) { return this.getStudentByStuNo(stuNo).getStuPic(); } @Override public List<Student> loadStudents(StudentQueryHelper helper) { DetachedCriteria criteria=this.genCriteriaByHelper(helper); // Session session=HibernateUtils.createSession(); Session session=this.getSession(); List<Student> stuList=null; /*注释这段事务控制代码的原因是因为我们已经将所有的事物委托给Spring事务控制去完成,这儿如果再开一个事务的话,会产生冲突。所以注释掉*/ // Transaction trans=session.beginTransaction(); // try{ criteria.addOrder(Order.asc("stuNo")); stuList=criteria.getExecutableCriteria(session).list(); // trans.commit(); // }catch(HibernateException e){ // e.printStackTrace(); // trans.rollback(); // }finally{ // if(session.isOpen()){ // session.close(); // } // } return stuList; } /** * Title:获得(生成)DetachedCriteria对象(条件分离对象) <br> * Description:根据传入的Helper生成DetachedCriteria对象<br> * @param helper 查询条件 * @return DetachedCriteria 条件分离对象 * @throws */ private DetachedCriteria genCriteriaByHelper(StudentQueryHelper helper){ DetachedCriteria criteria=DetachedCriteria.forClass(Student.class); if(StringUtils.isNotEmpty(helper.getQryStuNo())){ criteria.add(Restrictions.eq("stuNo", helper.getQryStuNo())); } if(StringUtils.isNotEmpty(helper.getQryStuName())){ criteria.add(Restrictions.like("stuName","%"+helper.getQryStuName()+"%")); } if(helper.getQryMinStuMark()!=null){ criteria.add(Restrictions.ge("stuMark", helper.getQryMinStuMark())); } if(helper.getQryMaxStuMark()!=null){ criteria.add(Restrictions.le("stuMark", helper.getQryMaxStuMark())); } if(StringUtils.isNotEmpty(helper.getQryStuSex())){ criteria.add(Restrictions.eq("stuSex", helper.getQryStuSex())); } if(StringUtils.isNotEmpty(helper.getQryStuOrigin())){ criteria.add(Restrictions.eq("stuOrigin", helper.getQryStuOrigin())); } if(helper.getQryClazzNo()!=null){ criteria.createCriteria("clazz").add(Restrictions.eq("clazzNo", helper.getQryClazzNo())); } return criteria; } @Override public Long cntStudentsByHelper(StudentQueryHelper helper) { DetachedCriteria detachedCriteria=this.genCriteriaByHelper(helper); //增加投影运算。就是我要做的事情类型 detachedCriteria.setProjection(Projections.rowCount()); long cnt=0; // Session session=HibernateUtils.createSession(); Session session=this.getSession(); // Transaction trans = session.beginTransaction(); // try{ cnt = Long.parseLong(detachedCriteria.getExecutableCriteria(session).list().get(0).toString()); // trans.commit(); // }catch(HibernateException e){ // e.printStackTrace(); // trans.rollback(); // }finally{ // if(session.isOpen()){ // session.close(); // } // } // return cnt; } @Override public List<Student> loadScopeStudentsByHelper(StudentQueryHelper helper,int beginIndex,int fetchSize) { DetachedCriteria detachedCriteria = this.genCriteriaByHelper(helper); detachedCriteria.addOrder(Order.asc("stuNo")); List<Student> stuList = null; // Session session = HibernateUtils.createSession(); Session session=this.getSession(); // Transaction trans = session.beginTransaction(); // try{ stuList = detachedCriteria.getExecutableCriteria(session) .setFirstResult(beginIndex) .setMaxResults(fetchSize) .list(); // trans.commit(); // }catch(HibernateException e) // { // e.printStackTrace(); // trans.rollback(); // }finally{ // if(session.isOpen()){ // session.close(); // } // } return stuList; } }
spring事务管理差不多结束了。下面是一些界面的css优化:
main.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8" isELIgnored="false"%> <%@ include file="/jsps/common-tags.jsp" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> <link rel="stylesheet" type="text/css" href="<c:url value="/css/application.css" ></c:url>"> <script> function exitSys(){ if(confirm("您确定要退出系统吗?")){ location.href="<s:url action="logout" namespace="/security"></s:url>"; } } </script> </head> <body> <div id="header"> <div id="productName">学生管理系统</div> <div></div> <div style="float:right;margin:10px;"> 操作员:${loginedUser.userName } <span class="linkSpan" onclick="logout();" title="点击离开系统">离开系统</span> </div> </div> <div> <div id="navigator"> <div class="menuitem"> <!-- target属性:决定啦这个链接的打开位置,默认是_blank --> <a href="<s:url action="loadClazzList" namespace="/clazz" ></s:url>" target="contentFrame">班级管理</a> </div> <div class="seperator"></div> <div class="menuitem"> <a href="<s:url action="toReg" namespace="/student"></s:url>" target="contentFrame">新生登记</a> </div> <div class="menuitem"> <a href="<s:url action="loadStudents" namespace="/student"></s:url>" target="contentFrame">学生管理</a> </div> </div> <div id="content"> <!-- iframe:inner frame(Window) --> <iframe id="contentFrame" width="99%" scrolling="yes" height="520px" frameborder="0" name="contentFrame" allowtransparency="true" src="<c:url value="/welcome.jsp"></c:url>"> </iframe> </div> </div> <div style="clear:both"></div> <%@ include file="/jsps/footer.jsp" %> </body> </html>
application.css文件的导入:
body,tr,td,th,div,span,ul,li,input,select,option,textarea{ font-size:12px; font-family:verdana; padding:0px; margin:0px; } #header{ height:80px; border-bottom:2px solid blue; } #productName{ font-size:30px; font-weight:bold; float:left; padding:10px; margin-top:20px; } #navigator{ width:130px; padding:10px; height:520px; border-right:2px solid blue; float:left; } #navigator .menuitem{ font-size:14px; text-align:center; margin-top:8px; } #navigator .seperator{ border-bottom:1px dotted blue; margin-top:10px; margin-bottom:10px; } #content{ float:left; width:1100px; } .linkspan{ color:blue; text-decoration:underline; cursor:hand; }