搭建开发环境:
Spring2.5需要的JAR文件:
spring-framework-2.5.6\dist\spring.jar
spring-framework-2.5.6\lib\jakarta-commons\commons-logging.jar
spring-framework-2.5.6\lib\aspectj\aspectjweaver.jar
Hibernate3.6需要的JAR文件
hibernate-distribution-3.6.0.Final\hibernate3.jar
hibernate-distribution-3.6.0.Final\lib\required\*
hibernate-distribution-3.6.0.Final\lib\jpa\hibernate-jpa-2.0-api-1.0.0.Final.jar
数据库驱动包
mysql-connector-java-5.1.7-bin.jar
方式一:
1.实体类与映射文件
package org.monday.hibernate1; import java.util.Date; public class Emp { private int id; // 编号 private String name; // 姓名 private int age; // 年龄 private double salary; // 薪水 private Date birthday; // 生日 public Emp() { } public Emp(int id, String name, int age, double salary, Date birthday) { this.id = id; this.name = name; this.age = age; this.salary = salary; this.birthday = birthday; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override public String toString() { return "Emp [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + ", birthday=" + birthday + "]"; } }
Emp.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 package="org.monday.hibernate1"> <class name="Emp" table="EMP"> <id name="id"> <generator class="assigned" /> </id> <property name="name" /> <property name="age" /> <property name="salary" /> <property name="birthday" /> </class> </hibernate-mapping>
2.开发Dao
package org.monday.hibernate1; import java.util.List; public interface EmpDao { /** 插入 */ public void insert(Emp emp); /** 更新*/ public void update(Emp emp); /** 删除*/ public void delete(Emp emp); /** 根据id删除 */ public void delete(int id); /** 根据id查询雇员的详细信息 */ public Emp findById(int id); /** 查询全部雇员信息 */ public List<Emp> findAll(); /** 根据雇员姓名查询其薪水 */ public double findSalary(String name); /** 查询部总记录数 */ public int totalCount(); /** 批量插入 */ public void insertBatch(List<Emp> emps); /** 批量删除 */ public void deleteBatch(int... ids); }
3.开发Dao实现类
package org.monday.hibernate1; import java.util.List; import javax.annotation.Resource; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; @Repository("empDao") public class EmpDaoImpl implements EmpDao { @Resource private SessionFactory sessionFactory; /* public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } */ /** 取得当前可用的Session */ private Session getSession(){ return sessionFactory.getCurrentSession(); } /** 插入 */ @Transactional public void insert(Emp emp) { getSession().save(emp); } /** 更新 */ @Transactional public void update(Emp emp) { getSession().update(emp); } /** 删除 */ @Transactional public void delete(Emp emp) { getSession().delete(emp); } /** 根据id删除 */ @Transactional public void delete(int id) { /** 方法一 */ /* Emp emp=(Emp) getSession().get(Emp.class,id); getSession().delete(emp); */ /** 方法二*/ getSession().createQuery("delete from Emp where id=?").setParameter(0, id).executeUpdate(); } /** 根据id查询雇员的详细信息 */ @Transactional(readOnly=true) public Emp findById(int id) { return (Emp) getSession().get(Emp.class,id); } /** 查询全部雇员信息 */ @Transactional(readOnly=true) public List<Emp> findAll() { return getSession().createQuery("from Emp").list(); } /** 根据雇员姓名查询其薪水 */ @Transactional(readOnly=true) public double findSalary(String name) { return (Double) getSession().createQuery("select e.salary from Emp e where e.name=?").setParameter(0, name).uniqueResult(); } /** 查询部总记录数 */ @Transactional(readOnly=true) public int totalCount() { return Integer.parseInt( getSession().createQuery("select count(id) from Emp").uniqueResult()+""); //return (Integer) getSession().createQuery("select count(id) from Emp").uniqueResult(); //会抛出java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer } /** 批量插入 */ @Transactional public void insertBatch(List<Emp> emps) { for (int i = 0; emps != null && i < emps.size(); i++) { getSession().save(emps.get(i)); if(i%20==0){ getSession().flush(); getSession().clear(); } } } /** 批量删除 */ @Transactional public void deleteBatch(int... ids) { /** 方法一 */ for (int i = 0; ids != null && i < ids.length; i++) { Emp emp=(Emp) getSession().get(Emp.class,ids[i]); getSession().delete(emp); if(i%20==0){ getSession().flush(); getSession().clear(); } } /** 方法二*/ /* StringBuffer hql=new StringBuffer(); hql.append("delete from Emp where id in"); hql.append("("); for (int i = 0; ids != null && i < ids.length; i++) { if(i==ids.length-1){ hql.append("?"); }else{ hql.append("?,"); } } hql.append(")"); Query query=getSession().createQuery(hql.toString()); for (int j=0; ids != null && j < ids.length; j++) { query.setParameter(j, ids[j]); } query.executeUpdate(); */ /** 方法三*/ /* StringBuffer hql=new StringBuffer(); hql.append("delete from Emp where id in"); hql.append("("); for (int i = 0; ids != null && i < ids.length; i++) { if(i==ids.length-1){ hql.append(ids[i]); }else{ hql.append(ids[i]+","); } } hql.append(")"); getSession().createQuery(hql.toString()).executeUpdate(); */ } }
这里的操作需要通过Spring容器来注入SessionFactory,从而获取Session进行一系列Hibernate操作,而不依赖于Spring的API,只不过SessionFactory要依赖Spring容器来注入。而事务使用注解配置。
4.Spring的配置文件beans.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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 配置注解扫描器 --> <context:annotation-config/> <!-- 指定要扫描的包 --> <context:component-scan base-package="org.monday.hibernate1"/> <!-- 将Hibernate的异常转变成Spring的DataAccessException异常 --> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> <!-- 配置sessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml"/> <property name="mappingLocations" value="org/monday/hibernate1/*.hbm.xml"/> </bean> <!-- 配置事务 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
5.测试
package org.monday.hibernate1; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { private ApplicationContext ctx = new ClassPathXmlApplicationContext("org/monday/hibernate1/beans1.xml"); private EmpDao empDao = (EmpDao) ctx.getBean("empDao"); @Test public void testInsert() { Emp emp = new Emp(101, "zy_test1", 21, 3000, randomDate("1980-01-01","1999-12-31")); empDao.insert(emp); } @Test public void testUpdate() { Emp emp = new Emp(1, "zy_test", 19, 1000, randomDate("1980-01-01","1999-12-31")); empDao.update(emp); } @Test public void testDeleteEmp() { Emp emp = new Emp(); emp.setId(100); empDao.delete(emp); } @Test public void testDeleteInt() { empDao.delete(99); } @Test public void testFindById() { Emp emp = empDao.findById(1); System.out.println(emp); } @Test public void testFindAll() { List<Emp> list = empDao.findAll(); for (Emp e : list) { System.out.println(e); } } @Test public void testFindSalary() { double salary = empDao.findSalary("zy_test"); System.out.println(salary); } @Test public void testTotalCount() { int count = empDao.totalCount(); System.out.println("共" + count + "条记录"); } @Test public void testInsertBatch() { List<Emp> emps = new ArrayList<Emp>(); for (int i = 1; i <= 100; i++) { int age = (int) (Math.random() * 100) + 1; double salary = (int) (Math.random() * 3000) + 1; Emp emp = new Emp(i, "zy_test" + i, age, salary, randomDate("1980-01-01", "1999-12-31")); emps.add(emp); } empDao.insertBatch(emps); } @Test public void testDeleteBatch() { int[] ids = {96,95}; empDao.deleteBatch(ids); } /** 在给定的日期范围内生成随即日期 */ private static Date randomDate(String beginDate, String endDate) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); try { long start = format.parse(beginDate).getTime(); long end = format.parse(endDate).getTime(); long time = Math.abs(start + (long) (Math.random() * (end - start))); return new Date(time); } catch (Exception e) { throw new RuntimeException(e); } } }
方式二:
直接看Dao实现类吧
package org.monday.hibernate2; import java.util.List; import org.springframework.orm.hibernate3.HibernateTemplate; public class EmpDaoImpl implements EmpDao { private HibernateTemplate hibernateTemplate; public void setHibernateTemplate(HibernateTemplate hibernateTemplate) { this.hibernateTemplate = hibernateTemplate; } /** 插入 */ public void insert(Emp emp) { hibernateTemplate.save(emp); } /** 更新 */ public void update(Emp emp) { hibernateTemplate.update(emp); } /** 删除 */ public void delete(Emp emp) { hibernateTemplate.delete(emp); } /** 根据id删除 */ public void delete(int id) { Emp emp = (Emp) hibernateTemplate.get(Emp.class, id); hibernateTemplate.delete(emp); } /** 根据id查询雇员的详细信息 */ public Emp findById(int id) { return (Emp) hibernateTemplate.get(Emp.class, id); } /** 查询全部雇员信息 */ public List<Emp> findAll() { return hibernateTemplate.find("from Emp"); } /** 根据雇员姓名查询其薪水 */ public double findSalary(String name) { List<Double> list = hibernateTemplate.find("select e.salary from Emp e where e.name=?", name); return list.size() > 0 ? list.get(0) : 0; } /** 查询部总记录数 */ public int totalCount() { List<Long> list = hibernateTemplate.find("select count(*) from Emp"); return list.size() > 0 ? Integer.parseInt(list.get(0)+"") : 0; } /** 批量插入 */ public void insertBatch(List<Emp> emps) { for (int i = 0; emps != null && i < emps.size(); i++) { hibernateTemplate.save(emps.get(i)); if (i % 20 == 0) { hibernateTemplate.flush(); hibernateTemplate.clear(); } } } /** 批量删除 */ public void deleteBatch(int... ids) { /** 方法一 */ for (int i = 0; ids != null && i < ids.length; i++) { Emp emp = (Emp) hibernateTemplate.get(Emp.class, ids[i]); hibernateTemplate.delete(emp); if (i % 20 == 0) { hibernateTemplate.flush(); hibernateTemplate.clear(); } } } }
这里注入的不在是SessionFactory而是HibernateTemplate,这是Spring为辅助Hibernate开发提供的模版类。
而事务不用注解了(之前写过了),用XML配置注解
此时Spring的配置文件编写如下:
<?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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置数据库连接信息 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/spring"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!-- 配置sessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> <!-- 个人觉得这么配置方便,不用将所有的映射文件都列出来,因为有时会忘记配置映射文件 --> <property name="mappingLocations" value="org/monday/hibernate2/*.hbm.xml"/> <!-- 或者 <property name="mappingResources"> <list> <value>org/monday/hibernate2/Emp.hbm.xml</value> </list> </property> --> </bean> <!-- 配置DAO --> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="empDao" class="org.monday.hibernate2.EmpDaoImpl"> <property name="hibernateTemplate" ref="hibernateTemplate"/> </bean> <!-- 配置事务 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <tx:advice id="tx" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*"/> <tx:method name="find*" read-only="true"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="perform" expression="execution( * org.monday.hibernate2.*.*(..))" /> <aop:advisor advice-ref="tx" pointcut-ref="perform"/> </aop:config> </beans>
方式三:
直接看Dao实现类吧。
package org.monday.hibernate3; import java.util.List; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; public class EmpDaoImpl extends HibernateDaoSupport implements EmpDao { /** 插入 */ public void insert(Emp emp) { getHibernateTemplate().save(emp); } /** 更新 */ public void update(Emp emp) { getHibernateTemplate().update(emp); } /** 删除 */ public void delete(Emp emp) { getHibernateTemplate().delete(emp); } /** 根据id删除 */ public void delete(int id) { Emp emp = (Emp) getHibernateTemplate().get(Emp.class, id); getHibernateTemplate().delete(emp); } /** 根据id查询雇员的详细信息 */ public Emp findById(int id) { return (Emp) getHibernateTemplate().get(Emp.class, id); } /** 查询全部雇员信息 */ public List<Emp> findAll() { return getHibernateTemplate().find("from Emp"); } /** 根据雇员姓名查询其薪水 */ public double findSalary(String name) { List<Double> list = getHibernateTemplate().find("select e.salary from Emp e where e.name=?", name); return list.size() > 0 ? list.get(0) : 0; } /** 查询部总记录数 */ public int totalCount() { List<Long> list = getHibernateTemplate().find("select count(*) from Emp"); return list.size() > 0 ? Integer.parseInt(list.get(0)+"") : 0; } /** 批量插入 */ public void insertBatch(List<Emp> emps) { for (int i = 0; emps != null && i < emps.size(); i++) { getHibernateTemplate().save(emps.get(i)); if (i % 20 == 0) { getHibernateTemplate().flush(); getHibernateTemplate().clear(); } } } /** 批量删除 */ public void deleteBatch(int... ids) { /** 方法一 */ for (int i = 0; ids != null && i < ids.length; i++) { Emp emp = (Emp) getHibernateTemplate().get(Emp.class, ids[i]); getHibernateTemplate().delete(emp); if (i % 20 == 0) { getHibernateTemplate().flush(); getHibernateTemplate().clear(); } } } }
继承了HibernateDaoSupport,这也是Spring提供的一个辅助类
而Spring的配置文件变动如下:
<!-- 配置DAO --> <!-- <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="empDao" class="org.monday.hibernate2.EmpDaoImpl"> <property name="hibernateTemplate" ref="hibernateTemplate"/> </bean> --> <bean id="empDao" class="org.monday.hibernate3.EmpDaoImpl"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
三种方式,我个人喜欢第一种。
因为不用依赖Spring的API,不过反过来一想,既然开发都依赖Spring框架了,那这点依赖又算什么。
哈,确实不算什么,只是觉得使用Hibernate的原生API比Spring的好用。(一家之言,欢迎拍转,呵呵~)
而关于配置文件,我认为还是不要写在一起的好,Hibernate的配置就用hibernate.cfg.xml,而Spring就用beans.xml将组件组装起来。类似于Struts2的“分离关注”思想吧。(谁该做的,就让谁做,不要大杂烩。)
最好JDBC的数据库连接配置也单独写在一个配置文件中。
关于实体类的映射文件建议还是配置在beans.xml中吧。不用每次开发完实体类都要在hibernate.cfg.xml中配置,有时太忙了就忘记了。(自己犯过这样的错误...)
在Sping中写成类似
<property name="mappingLocations" value="org/monday/hibernate3/*.hbm.xml"/>
通配符的形式,就不怕忘记啦。