Spring MVC + Spring + Hibernate整合 Spring 3.1.1 AND Hibernate 4.1.0

来源:互联网 发布:妈妈说就算域名在长廊 编辑:程序博客网 时间:2021/10/19 06:25

Spring MVC + Spring + Hibernate整合 Spring 3.1.1 AND Hibernate 4.1.0


1、搭建环境:推荐jar包下载地址:search.maven.org
2、编写web.xml
<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><display-name>rumourdie</display-name><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:/config/spring/applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><servlet><servlet-name>rumourdie</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath*:/config/spring/rumourdie-servlet.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>rumourdie</servlet-name><url-pattern>*.action</url-pattern></servlet-mapping><!-- 防止乱码 --><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>utf-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><!-- openSessionInViewFilter开启,不开启就会抛出 no session from current thread 由session.getCurrentSession()引起--><filter>          <filter-name>openSessionInViewFilter</filter-name>          <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>    </filter>    <filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><filter-mapping><filter-name>openSessionInViewFilter</filter-name><url-pattern>*.action</url-pattern></filter-mapping>  <welcome-file-list>    <welcome-file>index.jsp</welcome-file>  </welcome-file-list></web-app>
2、编写Spring MVC的配置文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">   <!-- 使用该标签表示启用spring mvc 的注解功能   默认会注册支持注解的类--><mvc:annotation-driven/><!-- 自动扫描,自动进行属性注入 -->   <context:component-scan base-package="org.lxl.rumourdie" />   <!-- 声明一个视图解析器 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/views/"p:suffix=".jsp"/></beans>

3、编写Spring IOC 配置文件ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:aop="http://www.springframework.org/schema/aop"       xmlns:tx="http://www.springframework.org/schema/tx"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:p="http://www.springframework.org/schema/p"       xsi:schemaLocation="       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd       ">    <context:component-scan base-package="org.lxl.rumourdie">    </context:component-scan>    <!-- 资源文件的读取 --><bean class="org.lxl.rumourdie.util.encryptProperty.EncryptPropertyPlaceholderConfigurer"    p:location="classpath:config/properties/db.properties" p:fileEncoding="utf-8"/>    <!-- 数据源的设置 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="${driverClassName}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/><property name="maxActive" value="${maxActive}"/><property name="maxIdle" value="${maxIdle}"/><property name="maxWait" value="${maxWait}"/><property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}"/><property name="removeAbandoned" value="${removeAbandoned}"/></bean><!-- sessionFactory --><bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"><!-- 配置数据源 --><property name="dataSource" ref="dataSource"/><!-- hibernate配置 --><property name="hibernateProperties"><props><prop key="hibernate.dialect">${dialect}</prop><prop key="hibernate.format_sql">${format_sql}</prop><prop key="hibernate.show_sql">${show_sql}</prop></props></property><property name="packagesToScan"><list><value>org.lxl.rumourdie.model.entity</value></list></property></bean>        <!-- 开启AOP监听 只对当前配置文件有效 --><aop:aspectj-autoproxy expose-proxy="true"/><!-- 开启注解事务 只对当前配置文件有效 -->  <tx:annotation-driven transaction-manager="txManager"/>    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">        <property name="sessionFactory" ref="sessionFactory"/>    </bean>    <tx:advice id="txAdvice" transaction-manager="txManager">        <tx:attributes>            <tx:method name="save*" propagation="REQUIRED" />            <tx:method name="add*" propagation="REQUIRED" />            <tx:method name="create*" propagation="REQUIRED" />            <tx:method name="insert*" propagation="REQUIRED" />            <tx:method name="update*" propagation="REQUIRED" />            <tx:method name="merge*" propagation="REQUIRED" />            <tx:method name="del*" propagation="REQUIRED" />            <tx:method name="remove*" propagation="REQUIRED" />            <tx:method name="put*" propagation="REQUIRED" />            <tx:method name="use*" propagation="REQUIRED"/>            <!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到-->            <tx:method name="get*" propagation="REQUIRED" read-only="true" />            <tx:method name="count*" propagation="REQUIRED" read-only="true" />            <tx:method name="find*" propagation="REQUIRED" read-only="true" />            <tx:method name="list*" propagation="REQUIRED" read-only="true" />            <tx:method name="*" read-only="true" />        </tx:attributes>    </tx:advice>    <aop:config expose-proxy="true">        <!-- 只对业务逻辑层实施事务 -->        <aop:pointcut id="txPointcut" expression="execution(* org.lxl.rumourdie.model.service..*.*(..))" />        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>    </aop:config></beans>
4、编写通用DAO(摘自这里)
package org.lxl.rumourdie.model.dao.hibernate.generic.dao;import java.io.Serializable;import java.util.List;import org.lxl.rumourdie.model.dao.hibernate.generic.dao.utils.GenericUtils;/** *  * @author lxl */@SuppressWarnings("unchecked")public abstract class HibernateGenericDao<T> extends HibernateDaoExtend<T> implements EntityDao<T>{protected Class<T> entityClass;public HibernateGenericDao(){/** * this.getClass()的目的是返回当前对象运行时的类 * 通过工具类GenericUtils返回泛型T的实际类对象 */entityClass = GenericUtils.getSuperClassGenericType(getClass());}public T get(Serializable id) {return get(entityClass,id);}public List<T> getAll() {return getAll(entityClass);}public String getIdName(Class clazz) {return null;}public void removeById(Serializable id) {removeById(entityClass,id);}public void save(T newInstance) {saveOrUpdate(newInstance);}/** * 查询全部,带排序 * @param orderBy * @param isAsc * @return */public List<T> getAllByOrder(String orderBy,boolean isAsc){return getAll(entityClass,orderBy,isAsc);}/** * 根据属性名和属性值查询对象 * @param propertyName * @param value * @return */public List<T> findBy(String propertyName,Object value){return findBy(entityClass, propertyName, value);}/** * 根据属性名和属性值进行查询对象,带排序 * @param propertyName * @param value * @param isAsc * @param orderBy * @return */public List<T> findBy(String propertyName,Object value,boolean isAsc,String orderBy){return findBy(entityClass, propertyName, value, orderBy, isAsc);}/** * 根据属性名和属性值进行查询对象,返回符合条件的唯一对象。 * 如果对象不唯一将抛出异常 * @param <T> * @param propertyName * @param value * @return */@SuppressWarnings("hiding")public <T> T findUniqueBy(String propertyName,Object value){return (T) findUniqueBy(entityClass, propertyName, value);}}

package org.lxl.rumourdie.model.dao.hibernate.generic.dao;import java.io.Serializable;import java.util.ArrayList;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.hibernate.Criteria;import org.hibernate.Query;import org.hibernate.SessionFactory;import org.hibernate.criterion.CriteriaSpecification;import org.hibernate.criterion.Criterion;import org.hibernate.criterion.Order;import org.hibernate.criterion.Projection;import org.hibernate.criterion.Projections;import org.hibernate.criterion.Restrictions;import org.hibernate.internal.CriteriaImpl;import org.hibernate.internal.CriteriaImpl.OrderEntry;import org.lxl.rumourdie.model.dao.hibernate.generic.dao.support.Page;import org.lxl.rumourdie.model.dao.hibernate.generic.dao.utils.Assert;import org.lxl.rumourdie.model.dao.hibernate.generic.dao.utils.BeanUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;/** * Dao的基类. *  * 提供分页函数和若干便捷查询方法,并对返回值作了泛型类型转换. * @author lxl */public abstract class HibernateDaoExtend<T>{    @Autowired    @Qualifier("sessionFactory")    private SessionFactory sessionFactory;@SuppressWarnings("unused")private static final Log log = LogFactory.getLog(HibernateDaoExtend.class);public void setSessionFactory(SessionFactory sessionFactory) {this.sessionFactory = sessionFactory;}/** * 获取全部的对象 * @param <T> * @param entityClass 对象类型 * @return  */@SuppressWarnings({ "unchecked", "hiding" })public <T>List<T> getAll(final Class<T> entityClass) {Criteria criteria = sessionFactory.getCurrentSession().createCriteria(entityClass);return criteria.list();}/** * 获取全部对象,带排序功能 * @param <T> * @param entityClass 实体对象 * @param orderBy 排序字段 * @param isAsc 升序或降序 * @return */@SuppressWarnings({ "hiding",  "unchecked" })public <T> List <T> getAll(final Class<T> entityClass,final String orderBy,final boolean isAsc){Assert.hasText(orderBy);if (isAsc)return sessionFactory.getCurrentSession().createCriteria(entityClass).addOrder(Order.asc(orderBy)).list();return sessionFactory.getCurrentSession().createCriteria(entityClass).addOrder(Order.desc(orderBy)).list();}/** * 保存对象 * @param newInstance */public void saveOrUpdate(final T newInstance){sessionFactory.getCurrentSession().saveOrUpdate(newInstance);}/** * 删除对象 * @param transientObject */public void remove(final T transientObject) {sessionFactory.getCurrentSession().delete(transientObject);}/** *  * @param entityClass * @param id */public void removeById(Class<T> entityClass, Serializable id) {remove( get(entityClass, id));}/** * 根据Id获取对象。 * @param <T> * @param entityClass * @param id 实体Id * @return 实体对象 */@SuppressWarnings({ "hiding", "unchecked" })public <T> T get(final Class<T> entityClass,final Serializable id) {return (T) sessionFactory.getCurrentSession().get(entityClass, id);}/** * 创建一个Query对象。 * @param hql * @param values * @return */public Query createQuery(String hql,Object...values){Assert.hasText(hql);Query query = sessionFactory.getCurrentSession().createQuery(hql);for(int i = 0;i<values.length;i++){query.setParameter(i, values[i]);}return query;}/** * 创建Criteria对象。 * @param <T> * @param entityClass * @param criterions * @return */@SuppressWarnings("hiding")public <T>Criteria createCriteria(Class<T> entityClass,Criterion...criterions){Criteria criteria = sessionFactory.getCurrentSession().createCriteria(entityClass);for(Criterion c:criterions){criteria.add(c);}return criteria;}/** * 创建Criteria对象,有排序功能。 * @param <T> * @param entityClass * @param orderBy * @param isAsc * @param criterions * @return */@SuppressWarnings("hiding")public <T>Criteria createCriteria(Class<T> entityClass,String orderBy,boolean isAsc,Criterion...criterions){Assert.hasText(orderBy);Criteria criteria = createCriteria(entityClass,criterions);if(isAsc){criteria.addOrder(Order.asc(orderBy));}else{criteria.addOrder(Order.desc(orderBy));}return criteria;}/** * 根据hql查询 * @param hql * @param values * @return */public List<?> find(final String hql,final Object...values){Assert.hasText(hql);return createQuery(hql, values).list();/*return (List) execute(new HibernateCallback(){public Object doInHibernate(Session session) {Query query = session.createQuery(hql);for(int i = 0;i<values.length;i++){query.setParameter(i, values[i]);}return query.list();}});*/}/** * 根据属性名和属性值查询. * * @return */@SuppressWarnings({ "unchecked", "hiding" })public <T>List<T> findBy(Class<T> entityClass,String propertyName,Object value){Assert.hasText(propertyName);return createCriteria(entityClass, Restrictions.eq(propertyName, value)).list();}/** * 根据属性名和属性值查询. 有排序 * @param <T> * @param entityClass * @param propertyName * @param value * @param orderBy * @param isAsc * @return */public <T>List<T> findBy(Class<T> entityClass,String propertyName,Object value,String orderBy,boolean isAsc){Assert.hasText(propertyName);Assert.hasText(orderBy);return createCriteria(entityClass, orderBy, isAsc, Restrictions.eq(propertyName, value)).list();}/** * 根据属性名和属性值 查询 且要求对象唯一. * * @return 符合条件的唯一对象. */public <T>T findUniqueBy(Class<T> entityClass,String propertyName,Object value){Assert.hasText(propertyName);return (T)createCriteria(entityClass, Restrictions.eq(propertyName, value)).uniqueResult();}/** * 分页 通过hql进行 * @param hql * @param pageNo * @param pageSize * @param values * @return */public Page pagedQuery(String hql,int pageNo,int pageSize,Object...values){Assert.hasText(hql);Assert.isTrue(pageNo>=1);String countQueryString = "select count(*)" + removeSelect(removeOrders(hql));System.out.println(countQueryString);List countList = find(countQueryString, values);long totalCount =  (Long) countList.get(0);System.out.println(totalCount);if(totalCount<1){return new Page();}int startIndex = Page.getStartOfPage(pageNo, pageSize);Query query = createQuery(hql,values);List<?> list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();return new Page(startIndex,totalCount,pageSize,list);}/** * 分页 通过criteria * @param criteria * @param pageNo * @param pageSize * @return */public Page pagedQuery(Criteria criteria,int pageNo,int pageSize){Assert.notNull(criteria);Assert.isTrue(pageNo>=1);CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;//先把Projection和OrderBy条件取出来,清空两者来执行Count操作Projection projection = criteriaImpl.getProjection();List<CriteriaImpl.OrderEntry> orderEntitys = null;try {orderEntitys=(List<OrderEntry>) BeanUtils.forceGetProperty(criteriaImpl, "orderEntries");BeanUtils.forceSetProperty(criteriaImpl, "orderEntries", new ArrayList());} catch (NoSuchFieldException e) {e.printStackTrace();}//取得总的数据数long totalCount = (Long) criteria.setProjection(Projections.rowCount()).uniqueResult();//将之前的Projection和OrderBy条件重新设回去criteria.setProjection(projection);if (projection == null) {criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);}try {BeanUtils.forceSetProperty(criteriaImpl, "orderEntries", orderEntitys);} catch (NoSuchFieldException e) {e.printStackTrace();}if(totalCount<1)return new Page();int startIndex = Page.getStartOfPage(pageNo, pageSize);List data = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();return new Page( startIndex, totalCount, pageSize, data);}/** * 分页查询函数 * @param entityClass * @param pageNo * @param pageSize * @param criterions * @return */public Page pagedQuery(Class<T> entityClass,int pageNo,int pageSize,Criterion...criterions){Criteria criteria = createCriteria(entityClass, criterions);return pagedQuery(criteria, pageNo, pageSize);}/** * 分页查询带排序 * @param entityClass * @param pageNo * @param pageSize * @param orderBy * @param isAsc * @param criterions * @return */public Page pagedQuery(Class<T> entityClass,int pageNo,int pageSize,String orderBy,boolean isAsc,Criterion...criterions){Criteria criteria = createCriteria(entityClass, orderBy, isAsc, criterions);return pagedQuery(criteria, pageNo, pageSize);}/** * 去除hql的select子句。 * @param hql * @return * @see #pagedQuery(String,int,int,Object[]) */private static String removeSelect(String hql){Assert.hasText(hql);int beginPos = hql.toLowerCase().indexOf("from");Assert.isTrue(beginPos!=-1,hql);return hql.substring(beginPos);}/** * 去除hql的orderBy子句。 * @param hql * @return * @see #pagedQuery(String,int,int,Object[]) */private static String removeOrders(String hql) {Assert.hasText(hql);Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE);Matcher m = p.matcher(hql);StringBuffer sb = new StringBuffer();while (m.find()) {m.appendReplacement(sb, "");}m.appendTail(sb);return sb.toString();}}

package org.lxl.rumourdie.model.dao.hibernate.generic.dao;import java.io.Serializable;import java.util.List;/** * 定义了针对单个实体的CRUD操作 * @author lxl */public interface EntityDao<T> {/** * 根据Id查找一个类型为T的对象。 *  * @param id 传入的Id的值 * @return 一个类型为T的对象 */T get(Serializable id);/** * 获取对象的全部集合,集合中的对象为T * @return 一组T对象的List集合 */List<T> getAll();/** * 持久化一个对象,该对象类型为T * @param newInstance 需要持久化的对象 */void save(T newInstance);/** * 删除一个已经被持久化的对象,该对象类型为T * @param transientObject 需要删除的持久化对象 */void remove(T transientObject);/** * 根据对象id删除一个对象,该对象类型为T * @param id 需要删除的对象的id */void removeById(Serializable id);/** * 获取Entity对像的主键名 * @param clazz * @return */String getIdName(Class<?> clazz);}
5、编写实体DAO
package org.lxl.rumourdie.model.dao.impl;import org.lxl.rumourdie.model.dao.hibernate.generic.dao.HibernateGenericDao;import org.lxl.rumourdie.model.entity.Attention;import org.springframework.stereotype.Repository;/** *@author LXL * DateTime 2013-3-5 下午10:47:58 */@Repositorypublic class AttentionDAOImpl extends HibernateGenericDao<Attention>{}

6、涉及到的工具类
package org.lxl.rumourdie.util.encryptProperty;import java.security.Key;import java.security.SecureRandom;import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;public class DESUtils {private static Key key;//存放密钥private static String KEY_STR = "key_for_LXL";//用该字符串生成密钥static {try {//返回一个DES的密钥生成器KeyGenerator generator = KeyGenerator.getInstance("DES");//用指定字符串初始化密钥生成器generator.init(new SecureRandom(KEY_STR.getBytes()));//生成密钥key = generator.generateKey();generator = null;} catch (Exception e) {throw new RuntimeException(e);}}/** * 对str进行DES加密 *  * @param str * @return */public static String getEncryptString(String str) {BASE64Encoder base64en = new BASE64Encoder();try {byte[] strBytes = str.getBytes("UTF8");Cipher cipher = Cipher.getInstance("DES");cipher.init(Cipher.ENCRYPT_MODE, key);byte[] encryptStrBytes = cipher.doFinal(strBytes);//得到加密后的字符数组return base64en.encode(encryptStrBytes);//使用base64进行编码} catch (Exception e) {throw new RuntimeException(e);}}/** * 对str进行DES解密 *  * @param str * @return */public static String getDecryptString(String str) {BASE64Decoder base64De = new BASE64Decoder();try {byte[] strBytes = base64De.decodeBuffer(str);//使用base64进行解码Cipher cipher = Cipher.getInstance("DES");cipher.init(Cipher.DECRYPT_MODE, key);byte[] decryptStrBytes = cipher.doFinal(strBytes);//根据密钥进行解码return new String(decryptStrBytes, "UTF8");//进行编码转换为字符串} catch (Exception e) {throw new RuntimeException(e);}}public static void main(String[] args){if (args == null || args.length < 1) {System.out.println("请输入要加密的字符,用空格分隔.");} else {for (String arg : args) {System.out.println(arg + ":" + getEncryptString(arg));}}}}

package org.lxl.rumourdie.util.encryptProperty;import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;public class EncryptPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {//需要解密的属性private String[] encryptPropNames ={"username","password"};@Overrideprotected String convertProperty(String propertyName, String propertyValue) {//如果是需要解密的属性就解密获得其值if(isEncryptProp(propertyName)){String decryptValue = DESUtils.getDecryptString(propertyValue);//System.out.println(decryptValue);return decryptValue;}else{return propertyValue;}}/** * 判断是否是加密的属性 * @param propertyName * @return */private boolean isEncryptProp(String propertyName){for(String encryptPropName:encryptPropNames){if(encryptPropName.equals(propertyName)){return true;}}return false;}}

7、进行简单测试
package test.dao; import static org.junit.Assert.assertNotNull;import org.junit.Before;import org.junit.Ignore;import org.junit.Test;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.unitils.UnitilsJUnit4;import org.unitils.dbunit.annotation.DataSet;import org.unitils.dbunit.annotation.ExpectedDataSet;import org.unitils.spring.annotation.SpringApplicationContext;import org.unitils.spring.annotation.SpringBeanByName;/**  * @author LvXinLiang   * @version 创建时间:2013-3-12 上午09:16:50  */public class UserDAOTest extends UnitilsJUnit4{/** * 构建Spring IOC 容器 */@SpringApplicationContext({"classpath:conf/springtest-servlet.xml","classpath:conf/applicationContext.xml"})private ClassPathXmlApplicationContext applicationContext;/** * 注入属性 */@SpringBeanByNameprivate UserDAO userDAO;@Beforepublic void check(){assertNotNull(applicationContext);assertNotNull(userDAO);}@Test@Ignorepublic void testInsertUser() {User user = new User("豆豆", "dou", 21);userDAO.insertUser(user);}}


这样简单的 Spring3.1.1 和Hibernate4.1.0就搭建好了