一、基础环境
1、Windows10、Java17、Maven3.8.8、Tomcat9.0.76、IDEA2022.3.3
2、已完成Maven项目的创建
2、已完成Struts2、Spring、Hibernate依赖配置
3、已完成实体类创建、Hibernate映射文件配置、第一种方法sessionFactory配置,并且以上配置已测试通过
4、已完成第二种方法数据源和会话工厂的配置、日志打印配置
二、框架版本
struts2:2.5.31
spring:5.3.27
hibernate:5.6.15.Final
三、实现并配置DAO
1、创建dao、impl目录
2、在dao包下创建EmployeeDao接口类,定义接口queryEmployeeByProperty、queryEmployeeByEmpNo、save
代码如下:
public interface EmployeeDao {
/**
* 根据员工的属性及属性的值查询员工信息
* @param property
* @param value
* @return
*/
List<Employee> queryEmployeeByProperty(String property, Object value);
/**
* 根据员工编号查询员工信息
* @param emp_no
* @return
*/
Employee queryEmployeeByEmpNo(String emp_no);
/**
* 保存员工信息
* @param employee
*/
void save(Employee employee);
}
3、在impl包下创建EmployeeDao接口的实现类EmployeeDaoImpl
IDEA快捷为在类名上使用快捷键“Alt+Enter”回车,然后选择指定的包,点击“OK”后会自动生成实现类。
4、在EmployeeDaoImpl类中注入sessionFactory
代码如下:
private SessionFactory sessionFactory;
/**
* 手动注入sessionFactory
* @param sessionFactory
*/
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
5、实现接口queryEmployeeByProperty、queryEmployeeByEmpNo、save
代码如下:
public class EmployeeDaoImpl implements EmployeeDao {
private SessionFactory sessionFactory;
/**
* 手动注入sessionFactory
* @param sessionFactory
*/
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public List<Employee> queryEmployeeByProperty(String property, Object value) {
String hql = "from Employee e where e." + property + "=:" + property;
return sessionFactory.openSession().createQuery(hql).setParameter(property, value).setMaxResults(2).list();
}
@Override
public Employee queryEmployeeByEmpNo(String emp_no) {
String hql = "from Employee e where e.emp_no = ?1";
return (Employee) sessionFactory.openSession().createQuery(hql).setParameter(1, emp_no).uniqueResult();
}
@Override
public void save(Employee employee) {
this.save(employee);
}
}
6、将employeeDao注入到Spring容器
官网参考:
Spring官网地址:https://docs.spring.io/spring-framework/reference/data-access/orm/hibernate.html
参考Implementing DAOs Based on the Plain Hibernate API
本地项目配置:
代码如下:
<!-- 将employeeDao注入到Spring容器 -->
<bean id="employeeDao" class="demo.employee.dao.impl.EmployeeDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
7、创建employeeDao的测试类,执行测试
IDEA创建测试类快捷键为在接口类中使用“Alt+Insert”,在弹出的窗口选择“Test”,然后勾选需要测试的方法,完成方法编写完成测试。
测试代码如下:
public class EmployeeDaoTest extends TestCase {
@Test
public void testQueryEmployeeByProperty() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeDao employeeDao = (EmployeeDao) applicationContext.getBean(EmployeeDao.class);
List<Employee> list = employeeDao.queryEmployeeByProperty("first_name", "Parto");
for (Employee employee:list) {
System.out.println(employee.toString());
}
}
@Test
public void testQueryEmployeeByEmpNo() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeDao employeeDao = applicationContext.getBean(EmployeeDao.class);
System.out.println(employeeDao.queryEmployeeByEmpNo(500000));
}
@Test
public void testSave() {
}
}
四、使用HibernateDaoSupport基类
1、DAO实现类继承HibernateDaoSupport。
2、无需在DAO中手动注入sessionFactory。
3、使用getHibernateTemplate()方法获取HibernateTemplate实例完成持久化操作。
代码如下:
public class EmployeeDaoImplPlus extends HibernateDaoSupport implements EmployeeDao {
@Override
public List<Employee> queryEmployeeByProperty(String property, Object value) {
/*
// 这里的hsql语句必须使用位置参数传递的方式,无法限制查询的条数
String hql = "from Employee e where e." + property + " = ?0";
return (List<Employee>) this.getHibernateTemplate().find(hql, value);
*/
/*
// 使用匿名内部类的方式实现某个接口
String hql = "from Employee e where e." + property + " =:" + property;
return this.getHibernateTemplate().execute(new HibernateCallback<List<Employee>>() {
@Override
public List<Employee> doInHibernate(Session session) throws HibernateException {
return session.createQuery(hql).setParameter(property, value).setMaxResults(2).list();
}
});
*/
// 使用lamda表达式转换上面的实现方式
String hql = "from Employee e where e." + property + " =:" + property;
return this.getHibernateTemplate().execute(session -> session.createQuery(hql).setParameter(property, value).setMaxResults(2).list());
}
@Override
public Employee queryEmployeeByEmpNo(Integer emp_no) {
// 使用位置参数传递的方式
String hql = "from Employee e where e.emp_no = ?1";
return (Employee) this.getHibernateTemplate().execute(session -> session.createQuery(hql).setParameter(1, emp_no).uniqueResult());
}
@Override
public void save(Employee employee) {
this.getHibernateTemplate().save(employee);
}
}
注:
由于这里使用了EmployeeDaoImplPlus实现类来实现EmployeeDao接口类,所以在Spring配置文件中要将employeeDao指向EmployeeDaoImplPlus,如图:
五、在继承与不继承HibernateDaoSupport时的差别
1、在不继承HibernateDaoSupport时,需要手动注入sessionFactory。
2、在不继承HibernateDaoSupport时,需要手动打开session对象,可能存在打开了session对象未关闭session对象的情况。
3、在不继承HibernateDaoSupport时,需要手动开启事务,可能存在开启了事务未commit的情况。
4、在使用手动完成2、3时,由于代码都是相同的,会存在代码冗余,因此Spring提供了HibernateTemplate用于简化Hibernate Dao编程。
5、如果要使用Spring提供的HibernateTemplate方法,只需实现类继承HibernateDaoSupport类。
六、实体类映射文件配置的几种方式
1、指定实体类映射文件第一种方式:mappingResources
当实体类映射文件很多时,需要不断加入文件路径的配置。
代码如下:
<property name="mappingResources">
<list>
<value>demo/employee/entity/employee.hbm.xml</value>
</list>
</property>
2、指定实体类映射文件第二种方式:mappingLocations
使用通配符进行配置实体类映射文件所在的路径(建议使用)。
代码如下:
<property name="mappingLocations" value="classpath*:demo/employee/entity/*.hbm.xml" />
3、指定实体类映射文件第三种方式:mappingDirectoryLocations
指定实体类映射文件所在的包名。
代码如下:
<property name="mappingDirectoryLocations" value="classpath:demo/employee/entity" />