Spring 4 整合 Hibernate 5 技术

在J2EE开发平台中,Spring是一种优秀的轻量级企业应用解决方案。Spring的核心技术就是IOC控制反转和AOP面向切面编程技术。

下面给出一个项目代码示例对Sping的相关技术进行讲解,该项目代码整合了最新的Spring4.2.5和Hibernate5.1技术,项目代码结构图如下:


下面给出详细配置代码

package com.kj.test.domain;

import java.io.Serializable;

/**
 * 用户实体类
 * @author KJ
 *
 */
public class User implements Serializable{

	private static final long serialVersionUID = 7178219894611819140L;
	/** 性别 */
	public static final int MAN = 1; //男
	public static final int FEMAN = 2; //女
	
	private Long id;
	/** 姓名 */
	private String name;
	/** 性别 */
	private Integer sex;
	/** 年龄 */
	private Integer age;

	public User () {
		
	}
	
	public User (Long id) {
		this.id = id;
	}

	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 Integer getSex() {
		return sex;
	}

	public void setSex(Integer sex) {
		this.sex = sex;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}
	

}

package com.kj.test.domain;

/**
 * 学生实体类
 * @author KJ
 *
 */
public class Student extends User {

	private static final long serialVersionUID = 7178219894611868560L;
	
	/** 学号 */
	private String studentId;
	/** 班级 */
	private NaturalClass naturalClass;
	/**学生信息修改*/
	private StudentInfoModify studentInfoModify;
	
	public Student () {
		
	}

	public String getStudentId() {
		return studentId;
	}

	public void setStudentId(String studentId) {
		this.studentId = studentId;
	}

	public NaturalClass getNaturalClass() {
		return naturalClass;
	}

	public void setNaturalClass(NaturalClass naturalClass) {
		this.naturalClass = naturalClass;
	}

	public StudentInfoModify getStudentInfoModify() {
		return studentInfoModify;
	}

	public void setStudentInfoModify(StudentInfoModify studentInfoModify) {
		this.studentInfoModify = studentInfoModify;
	}

}

package com.kj.test.domain;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

/**
 * 班级实体类
 * @author KJ
 *
 */
public class NaturalClass implements Serializable{

	private static final long serialVersionUID = 7178219894611819142L;

	private Long id;
	/** 名称 */
	private String name;
	/** 学生列表 */
	private Set<Student> students = new HashSet<Student>();

	public NaturalClass () {
		
	}

	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 Set<Student> getStudents() {
		return students;
	}

	public void setStudents(Set<Student> students) {
		this.students = students;
	}

}
package com.kj.test.domain;

import java.io.Serializable;

/**
 * 学生基本信息修改,信息修改后,需要经过管理员审核,审核通过后方可更新到Student学生实体类中
 * @author KJ
 *
 */
public class StudentInfoModify implements Serializable {
    
	private static final long serialVersionUID = -2705163477469273274L;
	/** 性别 */
	public static final int MAN = 1; //男
	public static final int FEMAN = 2; //女
	
	private Long id;
	/** 对应学生 */
	private Student student;
	/** 姓名 */
	private String name;
	/** 性别 */
	private Integer sex;
	/** 年龄 */
	private Integer age;
	/** 学号 */
	private String studentId;
	/** 班级 */
	private NaturalClass naturalClass;
	
	public StudentInfoModify() {
		
	}
	
	public StudentInfoModify(Long id) {
		this.id = id;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Student getStudent() {
		return student;
	}

	public void setStudent(Student student) {
		this.student = student;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getSex() {
		return sex;
	}

	public void setSex(Integer sex) {
		this.sex = sex;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public String getStudentId() {
		return studentId;
	}

	public void setStudentId(String studentId) {
		this.studentId = studentId;
	}

	public NaturalClass getNaturalClass() {
		return naturalClass;
	}

	public void setNaturalClass(NaturalClass naturalClass) {
		this.naturalClass = naturalClass;
	}

}
User.hbm.xml

<?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>
    <class name="com.kj.test.domain.User" table="User">
        <id name="id" column="id">
            <generator class="native" />
        </id>
        <property name="name" column="name" lazy="false"></property>
        <property name="sex" column="sex" lazy="false"></property>
        <property name="age" column="age" lazy="false"></property>
    </class>
</hibernate-mapping>

Student.hbm.xml

<?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>
	<!-- 继承类的配置:Student实体类继续User类 -->
  	<joined-subclass name="com.kj.test.domain.Student" extends="com.kj.test.domain.User" table="Student">
	  	<key column="id"></key>
	  	<property name="studentId" column="studentId" lazy="false"></property>
	  	<!-- 双向多对一关系:通过hibernate既可以从主控方实体加载被控方的实体,也可以从被控方加载对应的主控方实体 -->
	  	<many-to-one name="naturalClass" column="naturalClassId" lazy="false"></many-to-one>
		<!--  
		一对一关系:
		property-ref="student"指定StudentInfoModify类中对应的属性名, lazy="proxy"指定该属性在调用的时候才会被加载,
		cascade="delete"当删除Student对象的时候,对应的studentInfoModify对象也会被级联删除
		 -->
		<one-to-one name="studentInfoModify" property-ref="student" lazy="proxy" cascade="delete"></one-to-one>
	  	<!-- 如果是多对多关系,则新建一个类,这个类中引用多对多关系的两个类即可 -->
	  </joined-subclass>	
</hibernate-mapping>
StudentInfoModify.hbm.xml

<?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>
  <class name="com.kj.test.domain.StudentInfoModify" table="StudentInfoModify">
    <id name="id" column="id">
  		<generator class="native"></generator>
  	</id>
  	<property name="name" column="name" lazy="false"></property>
    <property name="sex" column="sex" lazy="false"></property>
    <property name="age" column="age" lazy="false"></property>
    <property name="studentId" column="studentId" lazy="false"></property>
    <!-- 单向多对一关联:只能通过主控方加载被控方数据,其中StudentInfoModify实体类是主控方 -->
  	<many-to-one name="naturalClass" column="naturalClassId" lazy="false"></many-to-one>
  	<!-- 一对一关联 -->
	<many-to-one name="student" column="stuId" unique="true" not-null="true" lazy="false"></many-to-one>
  </class>
</hibernate-mapping>
NaturalClass.hbm.xml

<?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>
    <class name="com.kj.test.domain.NaturalClass" table="NaturalClass">
        <id name="id" column="id">
            <generator class="native" />
        </id>
        <property name="name" column="name" lazy="false"></property>
        <!-- 双向多对一关系:通过hibernate既可以从主控方实体加载被控方的实体,也可以从被控方加载对应的主控方实体 -->
		<set name="students" inverse="true" lazy="false">
			<key column="naturalClassId"></key><!-- 对应Student类中naturalClass属性对应的column值 -->
			<one-to-many class="com.kj.test.domain.Student"/>
		</set>
    </class>
</hibernate-mapping>

上面是实体类和hibernate映射文件配置


接下面的是封装通用hibernate dao接口、service接口和分页工具类

通用泛型dao接口类:

package com.kj.test.dao;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import com.kj.test.util.PageResults;
import com.kj.test.util.RowMapper;
 
/**
 * @ClassName: IGenericDao
 * @Description: Dao封装接口
 * @author kj
 * @date 2016年5月2日18:00:00
 */
public interface IGenericDao<T, ID extends Serializable> {
     
    /**
     * <保存实体>
     * <完整保存实体>
     * @param t 实体参数
     */
    public abstract void save(T t);
 
    /**
     * <保存或者更新实体>
     * @param t 实体
     */
    public abstract void saveOrUpdate(T t);
 
    /**
     * <load>
     * <加载实体的load方法>
     * @param id 实体的id
     * @return 查询出来的实体
     */
    public abstract T load(ID id);
 
    /**
     * <get>
     * <查找的get方法>
     * @param id 实体的id
     * @return 查询出来的实体
     */
    public abstract T get(ID id);
 
    /**
     * <contains>
     * @param t 实体
     * @return 是否包含
     */
    public abstract boolean contains(T t);
 
    /**
     * <delete>
     * <删除表中的t数据>
     * @param t 实体
     */
    public abstract void delete(T t);
 
    /**
     * <根据ID删除数据>
     * @param Id 实体id
     * @return 是否删除成功
     */
    public abstract boolean deleteById(ID Id);
 
    /**
     * <删除所有>
     * @param entities 实体的Collection集合
     */
    public abstract void deleteAll(Collection<T> entities);
     
    /**
     * <执行Hql语句>
     * @param hqlString hql
     * @param values 不定参数数组
     */
    public abstract void queryHql(String hqlString, Object... values); 
     
    /**
     * <执行Sql语句>
     * @param sqlString sql
     * @param values 不定参数数组
     */
    public abstract void querySql(String sqlString, Object... values); 
 
    /**
     * <根据HQL语句查找唯一实体>
     * @param hqlString HQL语句
     * @param values 不定参数的Object数组
     * @return 查询实体
     */
    public abstract T getByHQL(String hqlString, Object... values);
 
    /**
     * <根据SQL语句查找唯一实体>
     * @param sqlString SQL语句
     * @param values 不定参数的Object数组
     * @return 查询实体
     */
    public abstract T getBySQL(String sqlString, Object... values);
 
    /**
     * <根据HQL语句,得到对应的list>
     * @param hqlString HQL语句
     * @param values 不定参数的Object数组
     * @return 查询多个实体的List集合
     */
    public abstract List<T> getListByHQL(String hqlString, Object... values);
 
    /**
     * <根据SQL语句,得到对应的list>
     * @param sqlString HQL语句
     * @param values 不定参数的Object数组
     * @return 查询多个实体的List集合
     */
    public abstract List<T> getListBySQL(String sqlString, Object... values);
     
    /**
     * 由sql语句得到List
     * @param sql
     * @param map
     * @param values
     * @return List
     */
    public List findListBySql(final String sql, final RowMapper map, final Object... values);
 
    /**
     * <refresh>
     * @param t 实体
     */
    public abstract void refresh(T t);
 
    /**
     * <update>
     * @param t 实体
     */
    public abstract void update(T t);
 
    /**
     * <根据HQL得到记录数>
     * @param hql HQL语句
     * @param values 不定参数的Object数组
     * @return 记录总数
     */
    public abstract Long countByHql(String hql, Object... values);
     
    /**
     * <HQL分页查询>
     * @param hql HQL语句
     * @param countHql 查询记录条数的HQL语句
     * @param pageNo 下一页
     * @param pageSize 一页总条数
     * @param values 不定Object数组参数
     * @return PageResults的封装类,里面包含了页码的信息以及查询的数据List集合
     */
    public abstract PageResults<T> findPageByFetchedHql(String hql, String countHql, int pageNo, int pageSize, Object... values);
 
}
通用泛型dao实现类
package com.kj.test.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.jdbc.Work;
import org.springframework.beans.factory.annotation.Autowired;

import com.kj.test.dao.IGenericDao;
import com.kj.test.util.PageResults;
import com.kj.test.util.RowMapper;

/**
 * @ClassName: GenericDaoImpl
 * @Description: IGenericDao实现
 * @author kj
 * @date 2016年5月2日18:00:00
 *
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class GenericDaoImpl<T, ID extends Serializable> implements IGenericDao<T, ID> {

	@Autowired
	private SessionFactory sessionFactory;
	protected Class<T> entityClass;

	public GenericDaoImpl() {

	}

	protected Class getEntityClass() {
		if (entityClass == null) {
			entityClass = (Class<T>) ((ParameterizedType) getClass()
					.getGenericSuperclass()).getActualTypeArguments()[0];
		}
		return entityClass;
	}

	/**
	 * <保存实体> <完整保存实体>
	 * 
	 * @param t
	 *            实体参数
	 * @see com.itv.launcher.util.IBaseDao#save(java.lang.Object)
	 */
	@Override
	public void save(T t) {
		this.getSession().save(t);
	}

	/**
	 * <保存或者更新实体>
	 * 
	 * @param t
	 *            实体
	 * @see com.itv.launcher.util.IBaseDao#saveOrUpdate(java.lang.Object)
	 */
	@Override
	public void saveOrUpdate(T t) {
		this.getSession().saveOrUpdate(t);
	}

	/**
	 * <load> <加载实体的load方法>
	 * 
	 * @param id
	 *            实体的id
	 * @return 查询出来的实体
	 * @see com.itv.launcher.util.IBaseDao#load(java.io.Serializable)
	 */
	@Override
	public T load(ID id) {
		T load = (T) this.getSession().load(getEntityClass(), id);
		return load;
	}

	/**
	 * <get> <查找的get方法>
	 * 
	 * @param id
	 *            实体的id
	 * @return 查询出来的实体
	 * @see com.itv.launcher.util.IBaseDao#get(java.io.Serializable)
	 */
	@Override
	public T get(ID id) {
		T load = (T) this.getSession().get(getEntityClass(), id);
		return load;
	}

	/**
	 * <contains>
	 * 
	 * @param t
	 *            实体
	 * @return 是否包含
	 * @see com.itv.launcher.util.IBaseDao#contains(java.lang.Object)
	 */
	@Override
	public boolean contains(T t) {
		return this.getSession().contains(t);
	}

	/**
	 * <delete> <删除表中的t数据>
	 * 
	 * @param t
	 *            实体
	 * @see com.itv.launcher.util.IBaseDao#delete(java.lang.Object)
	 */
	@Override
	public void delete(T t) {
		this.getSession().delete(t);
	}

	/**
	 * <根据ID删除数据>
	 * 
	 * @param Id
	 *            实体id
	 * @return 是否删除成功
	 * @see com.itv.launcher.util.IBaseDao#deleteById(java.io.Serializable)
	 */
	@Override
	public boolean deleteById(ID Id) {
		T t = get(Id);
		if (t == null) {
			return false;
		}
		delete(t);
		return true;
	}

	/**
	 * <删除所有>
	 * 
	 * @param entities
	 *            实体的Collection集合
	 * @see com.itv.launcher.util.IBaseDao#deleteAll(java.util.Collection)
	 */
	@Override
	public void deleteAll(Collection<T> entities) {
		for (Object entity : entities) {
			this.getSession().delete(entity);
		}
	}

	/**
	 * <执行Hql语句>
	 * 
	 * @param hqlString
	 *            hql
	 * @param values
	 *            不定参数数组
	 * @see com.itv.launcher.util.IBaseDao#queryHql(java.lang.String,
	 *      java.lang.Object[])
	 */
	@Override
	public void queryHql(String hqlString, Object... values) {
		Query query = this.getSession().createQuery(hqlString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		query.executeUpdate();
	}

	/**
	 * <执行Sql语句>
	 * 
	 * @param sqlString
	 *            sql
	 * @param values
	 *            不定参数数组
	 * @see com.itv.launcher.util.IBaseDao#querySql(java.lang.String,
	 *      java.lang.Object[])
	 */
	@Override
	public void querySql(String sqlString, Object... values) {
		Query query = this.getSession().createSQLQuery(sqlString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		query.executeUpdate();
	}

	/**
	 * <根据HQL语句查找唯一实体>
	 * 
	 * @param hqlString
	 *            HQL语句
	 * @param values
	 *            不定参数的Object数组
	 * @return 查询实体
	 * @see com.itv.launcher.util.IBaseDao#getByHQL(java.lang.String,
	 *      java.lang.Object[])
	 */
	@Override
	public T getByHQL(String hqlString, Object... values) {
		Query query = this.getSession().createQuery(hqlString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		return (T) query.uniqueResult();
	}

	/**
	 * <根据SQL语句查找唯一实体>
	 * 
	 * @param sqlString
	 *            SQL语句
	 * @param values
	 *            不定参数的Object数组
	 * @return 查询实体
	 * @see com.itv.launcher.util.IBaseDao#getBySQL(java.lang.String,
	 *      java.lang.Object[])
	 */
	@Override
	public T getBySQL(String sqlString, Object... values) {
		Query query = this.getSession().createSQLQuery(sqlString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		return (T) query.uniqueResult();
	}

	/**
	 * <根据HQL语句,得到对应的list>
	 * 
	 * @param hqlString
	 *            HQL语句
	 * @param values
	 *            不定参数的Object数组
	 * @return 查询多个实体的List集合
	 * @see com.itv.launcher.util.IBaseDao#getListByHQL(java.lang.String,
	 *      java.lang.Object[])
	 */
	@Override
	public List<T> getListByHQL(String hqlString, Object... values) {
		Query query = this.getSession().createQuery(hqlString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		return query.list();
	}

	/**
	 * <根据SQL语句,得到对应的list>
	 * 
	 * @param sqlString
	 *            HQL语句
	 * @param values
	 *            不定参数的Object数组
	 * @return 查询多个实体的List集合
	 * @see com.itv.launcher.util.IBaseDao#getListBySQL(java.lang.String,
	 *      java.lang.Object[])
	 */
	@Override
	public List<T> getListBySQL(String sqlString, Object... values) {
		Query query = this.getSession().createSQLQuery(sqlString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		return query.list();
	}

	/**
	 * 由sql语句得到List
	 * 
	 * @param sql
	 * @param map
	 * @param values
	 * @return List
	 * @see com.itv.launcher.util.IBaseDao#findListBySql(java.lang.String,
	 *      com.itv.launcher.util.RowMapper, java.lang.Object[])
	 */
	@Override
	public List findListBySql(final String sql, final RowMapper map,
			final Object... values) {
		final List list = new ArrayList();
		// 执行JDBC的数据批量保存
		Work jdbcWork = new Work() {
			public void execute(Connection connection) throws SQLException {
				PreparedStatement ps = null;
				ResultSet rs = null;
				try {
					ps = connection.prepareStatement(sql);
					for (int i = 0; i < values.length; i++) {
						setParameter(ps, i, values[i]);
					}
					rs = ps.executeQuery();
					int index = 0;
					while (rs.next()) {
						Object obj = map.mapRow(rs, index++);
						list.add(obj);
					}
				} finally {
					if (rs != null) {
						rs.close();
					}
					if (ps != null) {
						ps.close();
					}
				}
			}
		};
		this.getSession().doWork(jdbcWork);
		return list;
	}

	/**
	 * <refresh>
	 * 
	 * @param t
	 *            实体
	 * @see com.itv.launcher.util.IBaseDao#refresh(java.lang.Object)
	 */
	@Override
	public void refresh(T t) {
		this.getSession().refresh(t);
	}

	/**
	 * <update>
	 * 
	 * @param t
	 *            实体
	 * @see com.itv.launcher.util.IBaseDao#update(java.lang.Object)
	 */
	@Override
	public void update(T t) {
		this.getSession().update(t);
	}

	/**
	 * <根据HQL得到记录数>
	 * 
	 * @param hql
	 *            HQL语句
	 * @param values
	 *            不定参数的Object数组
	 * @return 记录总数
	 * @see com.itv.launcher.util.IBaseDao#countByHql(java.lang.String,
	 *      java.lang.Object[])
	 */
	@Override
	public Long countByHql(String hql, Object... values) {
		Query query = this.getSession().createQuery(hql);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		return (Long) query.uniqueResult();
	}

	/**
	 * <HQL分页查询>
	 * 
	 * @param hql
	 *            HQL语句
	 * @param countHql
	 *            查询记录条数的HQL语句
	 * @param pageNo
	 *            下一页
	 * @param pageSize
	 *            一页总条数
	 * @param values
	 *            不定Object数组参数
	 * @return PageResults的封装类,里面包含了页码的信息以及查询的数据List集合
	 * @see com.itv.launcher.util.IBaseDao#findPageByFetchedHql(java.lang.String,
	 *      java.lang.String, int, int, java.lang.Object[])
	 */
	@Override
	public PageResults<T> findPageByFetchedHql(String hql, String countHql,
			int pageNo, int pageSize, Object... values) {
		PageResults<T> retValue = new PageResults<T>();
		Query query = this.getSession().createQuery(hql);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		int currentPage = pageNo > 1 ? pageNo : 1;
		retValue.setCurrentPage(currentPage);
		retValue.setPageSize(pageSize);
		if (countHql == null) {
			ScrollableResults results = query.scroll();
			results.last();
			retValue.setTotalCount(results.getRowNumber() + 1);// 设置总记录数
		} else {
			Long count = countByHql(countHql, values);
			retValue.setTotalCount(count.intValue());
		}
		retValue.resetPageNo();
		List<T> itemList = query.setFirstResult((currentPage - 1) * pageSize)
				.setMaxResults(pageSize).list();
		if (itemList == null) {
			itemList = new ArrayList<T>();
		}
		retValue.setResults(itemList);

		return retValue;
	}

	/**
	 * @return the sessionFactory
	 */
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	/**
	 * @param sessionFactory
	 *            the sessionFactory to set
	 */
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	/**
	 * 
	 * @return session
	 */
	public Session getSession() {
		// 需要开启事物,才能得到CurrentSession
		return sessionFactory.getCurrentSession();
	}

	/**
	 * 
	 * 设置每行批处理参数
	 * 
	 * @param ps
	 * @param pos
	 *            ?占位符索引,从0开始
	 * @param data
	 * @throws SQLException
	 * @see [类、类#方法、类#成员]
	 */
	private void setParameter(PreparedStatement ps, int pos, Object data)
			throws SQLException {
		if (data == null) {
			ps.setNull(pos + 1, Types.VARCHAR);
			return;
		}
		Class dataCls = data.getClass();
		if (String.class.equals(dataCls)) {
			ps.setString(pos + 1, (String) data);
		} else if (boolean.class.equals(dataCls)) {
			ps.setBoolean(pos + 1, ((Boolean) data));
		} else if (int.class.equals(dataCls)) {
			ps.setInt(pos + 1, (Integer) data);
		} else if (double.class.equals(dataCls)) {
			ps.setDouble(pos + 1, (Double) data);
		} else if (Date.class.equals(dataCls)) {
			Date val = (Date) data;
			ps.setTimestamp(pos + 1, new Timestamp(val.getTime()));
		} else if (BigDecimal.class.equals(dataCls)) {
			ps.setBigDecimal(pos + 1, (BigDecimal) data);
		} else {
			// 未知类型
			ps.setObject(pos + 1, data);
		}

	}

}

service层接口

package com.kj.test.service;


import com.kj.test.dao.IGenericDao;
import com.kj.test.domain.User;


/**
 * 用户操作service接口
 * @author kj
 */
public interface IUserService extends IGenericDao<User, Long>{

//该接口继承了IGenericDao通用接口的所有抽象方法,另可自行定义所需方法

}

service层实现类

package com.kj.test.service.impl;


import com.kj.test.dao.impl.GenericDaoImpl;
import com.kj.test.domain.User;
import com.kj.test.service.IUserService;


/**
 * 用户操作service实现类
 * @author KJ
 *
 */
public class UserServiceImpl extends GenericDaoImpl<User, Long> implements IUserService {

//所有方法均已在GenericDaoImpl中实现,其中传递了泛型参数<User,Long>, 注意:泛型必须在编译时指定,不能在运行时再指定。


}

package com.kj.test.util;

import java.util.List;

/**
 * 分页封装类 用于做分页查询的基础类,封装了一些分页的相关属性
 * 
 * @author kj
 * @version v1.0
 * @param <T>
 */
public class PageResults<T> {

	// 下一页
	private int pageNo;

	// 当前页
	private int currentPage;

	// 每页个个数
	private int pageSize;

	// 总条数
	private int totalCount;

	// 总页数
	private int pageCount;

	// 记录
	private List<T> results;

	public int getPageCount() {
		return pageCount;
	}

	public void setPageCount(int pageCount) {
		this.pageCount = pageCount;
	}

	public int getPageNo() {
		if (pageNo <= 0) {
			return 1;
		} else {
			return pageNo > pageCount ? pageCount : pageNo;
		}
	}

	public void setPageNo(int pageNo) {
		this.pageNo = pageNo;
	}

	public List<T> getResults() {
		return results;
	}

	public void setResults(List<T> results) {
		this.results = results;
	}

	public int getCurrentPage() {
		return currentPage;
	}

	public void setCurrentPage(int currentPage) {
		this.currentPage = currentPage;
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize <= 0 ? 10 : pageSize;
	}

	public int getTotalCount() {
		return totalCount;
	}

	public void setTotalCount(int totalCount) {
		this.totalCount = totalCount;
	}

	public void resetPageNo() {
		pageNo = currentPage + 1;
		pageCount = totalCount % pageSize == 0 ? totalCount / pageSize
				: totalCount / pageSize + 1;
	}

}

package com.kj.test.util;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * RowMapper
 * 
 * @author kj
 * @version v1.0
 */
public interface RowMapper {
	
	public Object mapRow(ResultSet rs, int index) throws SQLException;
	
}

下面给出spring的关键配置文件

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns="http://java.sun.com/xml/ns/javaee" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>TestSpring</display-name>
  
  <!-- 启用Log4j监听 -->
  <!-- <listener>
      <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
   </listener> -->
  <!-- 启用spring监听 -->
  <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!-- 加载spring相关的配置文件 -->
  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:/applicationContext.xml</param-value> <!-- 或者 <param-value>classpath*:/applicationContext.xml</param-value> -->
  </context-param>
  

  <!-- 事务处理拦截器**必须配置在前面 不添加报Could not obtain transaction-synchronized Session for current thread错误**,也可以在spring配置事务解决 -->
  <!--<filter>
	<filter-name>SpringOpenSessionInViewFilter</filter-name>
		<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
	</filter>
  <filter-mapping>
    <filter-name>SpringOpenSessionInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
   -->
   
  <!-- filter配置示例 -->
  <filter>
  	<filter-name>MyFilter</filter-name>
  	<filter-class>com.kj.test.action.MyFilter</filter-class>
  	<init-param>
  		<param-name>encode</param-name>
  		<param-value>UTF-8</param-value>
  	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>MyFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
       http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd">

	<!-- 引入properties文件 : 注入property-->
	<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="locations">
            <list>
                <value>classpath*:/mysql.properties</value>
            </list>
        </property>
    </bean>
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="ignoreResourceNotFound" value="false" />
        <property name="properties" ref="configProperties" />
    </bean>
    
	<!-- 配置dbcp数据库连接池,destroy-method="close"的作用是当数据库连接不使用的时候,就把该连接重新放到数据池中,方便下次使用调用 -->
	<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
		<!-- 设置数据库驱动名称 -->
		<property name="driverClassName" value="${driverClassName}"></property>
		<!-- 设置数据库连接URL -->
		<property name="url" value="${url}"></property>
		<!-- 设置数据库用户名 -->
		<property name="username" value="${username}"></property>
		<!-- 设置数据库密码 -->
		<property name="password" value="${password}"></property>
		<!-- 设置连接池初始值 -->
		<property name="initialSize" value="${initialSize}"></property>
		<!-- 池里不会被释放的最多空闲连接数量。设置为0时表示无限制。 -->
		<property name="maxIdle" value="${maxIdle}"></property>
		<!-- 在不新建连接的条件下,池中保持空闲的最少连接数。 -->
		<property name="minIdle" value="${minIdle}"></property>
		<!-- 自动回收超时时间(以秒数为单位) -->
		<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}"></property>
		<!-- 设置在自动回收超时连接的时候打印连接的超时错误 -->
		<property name="logAbandoned" value="${logAbandoned}"></property>
	</bean>

	<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="mappingResources">
			<list>
				<value>com/kj/test/domain/User.hbm.xml</value>
				<value>com/kj/test/domain/Student.hbm.xml</value>
				<value>com/kj/test/domain/StudentInfoModify.hbm.xml</value>
				<value>com/kj/test/domain/NaturalClass.hbm.xml</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<!-- 数据库方言,当前使用的是MySQL数据库 -->
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
				<!-- 根据实体类和映射文件自动更新生成表结构 -->
				<prop key="hibernate.hbm2ddl.auto">update</prop>
				<!-- 输出所有SQL语句到控制台 -->
				<prop key="hibernate.show_sql">false</prop>
				<!-- 在log和console中打印出更漂亮的SQL -->
				<prop key="hibernate.format_sql">true</prop>
				<prop key="hibernate.query.substitutions">true 1, false 0</prop>
				<prop key="hibernate.max_fetch_depth">3</prop>
				<prop key="hibernate.default_entity_mode">pojo</prop>
				<prop key="hibernate.default_batch_fetch_size">16</prop>
				<prop key="hibernate.jdbc.batch_size">20</prop>
				<prop key="hibernate.order_updates">true</prop>
				<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>
				<prop key="hibernate.cache.use_second_level_cache">true</prop>
				<prop key="hibernate.generate_statistics">true</prop>
				<prop key="hibernate.cache.use_structured_entries">true</prop>
			</props>
		</property>
		<!-- 代码/稳定对象缓存配置:对于很少修改更新删除的对象,可配置缓存提高系统查询性能,nonstrict-read-write为不严格读写方式缓存 -->
		<!-- <property name="entityCacheStrategies">
			<props>
				<prop key="com.kj.test.domain.NaturalClass">nonstrict-read-write</prop>
			</props>
		</property> -->
	</bean>
	
	<!-- 配置声明式事务管理 -->
	<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>

	<!-- 事务通知 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			 <!--指定当前方法以非事务方式执行操作,如果当前存在事务,就把当前事务挂起,等我以非事务的状态运行完,再继续原来的事务。 查询定义即可read-only="true"  表示只读 -->
			<tx:method name="get*" read-only="true" />
			<tx:method name="find*" read-only="true"/>
			<tx:method name="count*" read-only="true"/>
			<tx:method name="firstResult" read-only="true"/>
			<tx:method name="uniqueResult" read-only="true"/>
			<!--事务执行方式 REQUIRED:指定当前方法必需在事务环境中运行, 如果当前有事务环境就加入当前正在执行的事务环境, 如果当前没有事务,就新建一个事务。这是默认值。 -->
			<tx:method name="*" />
		</tx:attributes>
	</tx:advice>
	
	<!-- AOP配置 -->
	<aop:config>
		<aop:pointcut id="serviceMethods" expression="execution(public * com.kj.test.dao..*.*(..))"/><!--切入点,是dao层而不是service层 -->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/><!--在指定切入点切入事务通知 -->
	</aop:config>
	
	<!-- DAO confignations -->
	<bean id="genericDao" class="com.kj.test.dao.impl.GenericDaoImpl">
		<property name="sessionFactory" ref="sessionFactory"></property><!-- IOC依赖注入 -->
	</bean>
	
	
	<!-- Service confignations-->
	<bean id="userService" class="com.kj.test.service.impl.UserServiceImpl">
		<property name="sessionFactory" ref="sessionFactory"></property><!-- IOC依赖注入 -->
	</bean>
	
	
	<import resource="classpath*:/webBeans.xml" />
</beans>

mysql.properties

########\u6570\u636e\u5e93\u8fde\u63a5\u4fe1\u606f#######
driverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/kj
username = root
password = root
initialSize = 10
maxIdle = 30
minIdle = 5
removeAbandonedTimeout = 3000
logAbandoned = false
########\u6ce8\u610f\u683c\u5f0f#######
log4j.properties
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

webBeans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
       http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd">
       
	<!-- just for test ,scope还可以取值singleton和session-->
	<bean id="userBean" class="com.kj.test.action.UserBean" scope="prototype">
		<property name="userService" ref="userService"></property><!-- IOC依赖注入 -->
	</bean>
</beans>

以上就是所有的配置文件和接口实现

下面提供action控制操作类代码如下:

package com.kj.test.action;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.kj.test.dao.impl.GenericDaoImpl;
import com.kj.test.domain.User;
import com.kj.test.service.IUserService;

public class UserBean implements Serializable {

	private static final long serialVersionUID = -7754405684414619372L;

	private User user;

	private IUserService userService;

	public UserBean() {
		super();
	}

	public void addUser(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// 获取页面传递过来的参数
		String name = request.getParameter("name");
		String sex = request.getParameter("sex");
		String age = request.getParameter("age");
		User user = new User(); // 实例化用户类
		try {
			user.setAge(Integer.parseInt(age));
		} catch (Exception e) {
		}
		try {
			user.setSex(Integer.parseInt(sex));
		} catch (Exception e) {
		}
		user.setName(name);
		boolean result = false;
		try {
			userService.saveOrUpdate(user);
			result = true;
		} catch (Exception e) {
			result = false;
			System.out.println("添加用户失败");
			e.printStackTrace();
		}
		String url;
		if (result) {
			getUserList(request, response);
		} else {
			getErrorMessage(request, response);
		}
	}

	public void getUserList(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		String hql = "from User";// hql查询语句
		List<User> userList = new ArrayList<User>();
		userList = userService.getListByHQL(hql, null);
		request.setAttribute("users", userList);
		String url = "manageUser.jsp";
		RequestDispatcher dispathcer = request.getRequestDispatcher(url);
		dispathcer.forward(request, response);

	}

	public void getErrorMessage(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		String url = "error.jsp";
		RequestDispatcher dispathcer = request.getRequestDispatcher(url);
		dispathcer.forward(request, response);

	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public IUserService getUserService() {
		return userService;
	}

	public void setUserService(IUserService userService) {
		this.userService = userService;
	}

}


过滤中文字符Filter
package com.kj.test.action;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class MyFilter implements Filter {
	
	private String encode;

	public MyFilter() {
		
    }

	public void destroy() {
		
	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

		if (encode != null) {
			request.setCharacterEncoding(encode);
			response.setContentType("text/html;charset="+encode);
		}
		chain.doFilter(request, response);
		
	}

	public void init(FilterConfig fConfig) throws ServletException {
		encode = fConfig.getInitParameter("encode");
	}

}


最后给出jsp页面代码如下:

index.jsp

<%@page import="org.springframework.web.bind.ServletRequestUtils"%>
<%@page import="com.kj.test.action.UserBean"%>
<%@page import="org.springframework.web.context.support.WebApplicationContextUtils"%>
<%@page import="org.springframework.web.context.WebApplicationContext"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(application);
	UserBean userBean = (UserBean)context.getBean("userBean");
	String beanAction = ServletRequestUtils.getStringParameter(request, "beanAction","");
	if (beanAction.equals("save")) {
		userBean.addUser(request, response);
	} else if (beanAction.equals("list")) {
		userBean.getUserList(request, response);
	}
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>添加用户入口</title>
	<script language="JavaScript" type="text/JavaScript">
		function doAction(formId, actionName) {
			document.getElementById("beanAction").value = actionName;
			document.getElementById(formId).submit();
		}
	</script>
</head>
<body>
	<form id="actionForm" action="" method="post">
		<input id="beanAction" name="beanAction" type="hidden" value=""/>
		<div style="margin-top:100px;text-align:center;margin-bottom:10px;font-size:24px;font-weight:bolder">添加用户页面</div>
		<table align="center" cellpadding="0" cellspacing="0" >
			<tr>
				<td style="text-align:right">姓名:</td>
				<td style="text-align:left"><input type="text" name="name" value="" required/></td>
			</tr>
			<tr>
				<td style="text-align:right">性别:</td>
				<td style="text-align:left"><input type="radio" name="sex" value="1" required/>男 <input type="radio" name="sex" value="2" required/>女</td>
			</tr>
			<tr>
				<td style="text-align:right">年龄:</td>
				<td style="text-align:left"><input type="text" name="age" value="" required/></td>
			</tr>
		</table>
		<div style="margin-top:10px;text-align:center;"><input type="button" value="增加用户" onClick="doAction(this.form.id,'save');"/>  <input type="button" value="管理用户" onClick="doAction(this.form.id,'list');"/></div>
	</form>
</body>
</html>
manageUser.jsp

<%@page import="org.springframework.web.context.support.WebApplicationContextUtils"%>
<%@page import="org.springframework.web.bind.ServletRequestUtils"%>
<%@page import="com.kj.test.action.UserBean"%>
<%@page import="org.springframework.web.context.WebApplicationContext"%>
<%@page import="com.kj.test.domain.User"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%
	pageContext.setAttribute("MAN",User.MAN);
	pageContext.setAttribute("FEMAN",User.FEMAN);
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>管理用户页面</title>
</head>
<body>
<form id="actionForm" action="" method="post">
	<div style="margin-top:100px;text-align:center;margin-bottom:10px;font-size:24px;font-weight:bolder">管理用户页面</div>
	<table align="center" border="1" cellpadding="0" cellspacing="0" >
		<c:set var="userList" value="${requestScope.users }" />
		<c:if test="${not empty userList }">
			<tr>
				<th style="text-align:center;width:200px;">主键ID</th>
				<th style="text-align:center;width:200px;">姓名</th>
				<th style="text-align:center;width:200px;">性别</th>
				<th style="text-align:center;width:200px;">年龄</th>
			</tr>
			<c:forEach items="${userList }" var="user">
				<tr>
					<td style="text-align:center;width:200px;"><c:out value="${user.id }"/></td>
					<td style="text-align:center;width:200px;"><c:out value="${user.name }"/></td>
					<td style="text-align:center;width:200px;"><c:if test="${user.sex == MAN}">男</c:if><c:if test="${user.sex == FEMAN}">女</c:if></td>
					<td style="text-align:center;width:200px;"><c:out value="${user.age }"/>岁</td>
				</tr>
			</c:forEach>
		</c:if>
		<c:if test="${empty userList }">
			<div style="margin-top:20px;text-align:center;margin-bottom:10px;font-size:18px;font-weight:bolder;color:red">对不起,当前还没有用户记录,请先返回添加页面进行添加。</div>
		</c:if>
	</table>
	<div style="margin-top:20px;text-align:center;"><a href="index.jsp">返回添加页面</a></div>
</form>
</body>
</html>

error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>错误页面</title>
</head>
<body>
	<div style="color:red;text-align:center;margin-top:100px;font-size: 20px;">
		操作失败
	</div>
</body>
</html>





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值