基本原理:由Spring来管理Hibernate的SessionFactory
方式一:零障碍整合(了解)
- 配置好 hibernate.cfg.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 配置数据库连接 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/sshtest</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- Hibernate的方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 显示sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 格式化sql语句 -->
<property name="hibernate.format_sql">true</property>
<!-- 自动创建表 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 设置连接提供者 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!-- c3p0连接配置 -->
<property name="hibernate.c3p0.max_size">20</property><!-- 最大连接数 -->
<property name="hibernate.c3p0.min_size">5</property><!-- 最小连接数 -->
<property name="hibernate.c3p0.timeout">120</property><!-- 超时 -->
<property name="hibernate.c3p0.idle_test_period">3000</property><!-- 空闲连接 -->
<!-- 配置映射文件 -->
<mapping resource="com/zhangquanli/sshxml/domain/Person.hbm.xml"/>
</session-factory>
</hibernate-configuration>
- 将 sessionFactory 交由 Spring 容器来管理
- Spring 中提供了 LocalSessionFactory 来加载 hibernate.cfg.xml 文件
- 注意:LocalSessionFactory 类针对 Hibernate 的不同版本,有不同的实现类
<!-- spring整合hibernate方式一 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml"/> </bean>
- 在 web.xml 中配置监听器,在服务器启动的时候加载 Spring 的配置文件
<!-- 配置 ContextLoaderListener 监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置 applicationContext.xml 路径 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
- 当工程加载到服务器后,如果可以自动创建表,就代表Spring整合Hibernate成功。因为在 hibernate.cfg.xml 配置文件中设置了自动创建表。
方式二:由 Spring 管理 Hibernate 的配置文件(重点)
- 在 applicationContext.xml 引入 db.properties 文件
<!-- 引入properties文件 -->
<context:property-placeholder location="classpath:db.properties"/>
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/sshtest
jdbc.username=root
jdbc.password=root
- 配置C3P0连接池
<!-- 配置C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
- 创建 LocalSessionFactoryBean
- 由 Spring 管理 Hibernate 中的 SessionFactory
<!-- 创建sessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" >
<!-- 注入连接池 -->
<property name="dataSource" ref="dataSource"/>
<!-- 配置Hibernate -->
<property name="hibernateProperties">
<!-- 以下属性在书写时不能省略hibernate -->
<!-- <props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props> -->
<!-- 上述props可以简写成以下方案 -->
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.hbm2ddl.auto=update
</value>
</property>
<!-- 加载映射文件 -->
<property name="mappingResources">
<list>
<value>com/zhangquanli/sshxml/domain/Person.hbm.xml</value>
</list>
</property>
</bean>
- 映射文件加载方式
- <font color="red">
mappingResources
</font> 类似于<mappring resource=""/>
<property name="mappingResources"> <list> <value>com/zhangquanli/sshxml/domain/Person.hbm.xml</value> </list> </property>
- <font color="red">
mappingLocations
</font> 根据类路径加载 classpath:路径
<property name="mappingLocations"> <list> <value>classpath:com/zhangquanli/sshxml/domain/Person.hbm.xml</value> </list> </property>
- <font color="red">
mappingDirectoryLocations
</font> 加载目录下所有映射文件
<property name="mappingDirectoryLocations"> <list> <value>classpath:com/zhangquanli/sshxml/domain</value> </list> </property>
- <font color="red">
mappingJarLocations
</font> 加载jar文件中的映射文件
- <font color="red">
- 由 Spring 管理 Hibernate 的配置文件时,不再需要 hibernate.cfg.xml 配置文件。因为 applicationContext.xml 文件中,就可以完成 Hibernate 的配置。
Spring 整合 Hibernate 后的 Dao
- 编写持久层代码
- Spring 整合 Hibernate 后,Dao需要继承 HibernateDaoSupport
package com.zhangquanli.sshxml.dao; import java.util.List; import org.springframework.orm.hibernate5.support.HibernateDaoSupport; import com.zhangquanli.sshxml.domain.User; public class UserDaoImpl extends HibernateDaoSupport implements IUserDao { @Override public void add(User user) { getHibernateTemplate().save(user);//session.save() } @Override public void update(User user) { getHibernateTemplate().update(user);//session.update() } @Override public void del(User user) { getHibernateTemplate().delete(user);//session.delete(); } @Override public User findById(Integer id) { return getHibernateTemplate().get(User.class, 1);//session.get() } @Override @SuppressWarnings("unchecked") public List<User> findAll() { return (List<User>) getHibernateTemplate().find("from User");//session.createQuery(hql).list() } }
- 声明 dao
- 在 HibernateDaoSupport 中注入 SessionFactory 获取 HibernateTemplate
- HibernateTemplate 是对 Hibernate 操作的简单封装
<!-- dao --> <bean id="userDao" class="com.zhangquanli.sshxml.dao.UserDaoImpl"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
- 编写业务层代码
package com.zhangquanli.sshxml.service;
import java.util.List;
import com.zhangquanli.sshxml.dao.IUserDao;
import com.zhangquanli.sshxml.domain.User;
public class UserServiceImpl implements IUserService {
private IUserDao userDao;
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
@Override
public void add(User user) {
userDao.add(user);
}
@Override
public void update(User user) {
userDao.update(user);
}
@Override
public void del(User user) {
userDao.del(user);
}
@Override
public User findById(Integer id) {
return userDao.findById(id);
}
@Override
public List<User> findAll() {
return userDao.findAll();
}
}
- 声明 service
<!-- service -->
<bean id="userService" class="com.zhangquanli.sshxml.service.UserServiceImpl">
<property name="userDao" ref="userDao" />
</bean>
- 在 applicationContext.xml 中配置事务管理
<!-- 声明式事务管理 -->
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="find*" read-only="true"/>
<tx:method name="add"/>
<tx:method name="update"/>
<tx:method name="del"/>
</tx:attributes>
</tx:advice>
<!-- 切面 -->
<aop:config>
<aop:pointcut expression="execution(* com.zhangquanli.sshxml.service.*..*(..))" id="myPointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"/>
</aop:config>
- 编写测试代码
package com.zhangquanli.sshxml.service;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.zhangquanli.sshxml.domain.User;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class UserServiceImplTest {
@Autowired
private IUserService userService;
@Test
public void testAdd() {
User user = new User();
user.setName("lis");
user.setAge(29);
user.setSex("女");
userService.add(user);
}
@Test
public void testUpdate() {
User user = userService.findById(2);
user.setName("黄珊珊");
userService.update(user);
}
@Test
public void testDel() {
User user = userService.findById(2);
userService.del(user);
}
@Test
public void testFindById() {
User user = userService.findById(2);
System.out.println(user);
}
@Test
public void testFindAll() {
List<User> list = userService.findAll();
System.out.println(list);
}
}
HibernateTemplate API
- 增删改
- <font color="red">
Serializable save(Object entity)
</font> - <font color="red">
void update(Object entity)
</font> - <font color="red">
void saveOrUpdate(Object entity)
</font> - <font color="red">
void delete(Object entity)
</font>
- <font color="red">
- 查
- <font color="red">
<T> T get(Class<T> entityClass, Serializable id)
</font> - <font color="red">
<T> T load(Class<T> entityClass, Serializable id)
</font> - <font color="red">
List<?> find(String queryString, Object... values)
</font> - <font color="red">
List<?> findByCriteria(DetachedCriteria criteria)
</font> - <font color="red">
List<?> findByNamedQuery(String queryName, Object... values)
</font>
- <font color="red">
- 一级缓存相关
- <font color="red">
void evict(Object entity)
</font> - <font color="red">
void clear()
</font>
- <font color="red">
- 一级缓存与数据库交互
- <font color="red">
void flush()
</font> - <font color="red">
void refresh(Object entity)
</font>
- <font color="red">
- 演示 <font color="red">
findByCriteria
</font> 方法- 创建 DetachedCriteria 对象
public void testFindByCriteria() { DetachedCriteria criteria = DetachedCriteria.forClass(User.class); criteria.add(Restrictions.gt("age", 20)); List<User> list = userService.findByCriteria(criteria); System.out.println(list); }
- 在dao层调用 findByCriteria 方法
public List<User> findByCriteria(DetachedCriteria criteria) { return (List<User>) getHibernateTemplate().findByCriteria(criteria); }
- 演示 <font color="red">
findByNamedQuery
</font> 方法- 在 User.hbm.xml 文件中定义 hql 和 sql
<query name="findUserByHQL"> from User where id>? </query> <sql-query name="findUserBySQL"> <return class="com.zhangquanli.sshxml.domain.User"/> select * from t_user </sql-query>
- 持久层代码
public List<User> findByNamedQueryHQL(Integer id) { return (List<User>) getHibernateTemplate().findByNamedQuery("findUserByHQL", id); } public List<User> findByNamedQuerySQL() { return (List<User>) getHibernateTemplate().findByNamedQuery("findUserBySQL"); }
- 测试代码
@Test public void testFindByNamedQueryHQL() { List<User> list = userService.findByNamedQueryHQL(2); System.out.println(list); } @Test public void testFindByNamedQuerySQL() { List<User> list = userService.findByNamedQuerySQL(); System.out.println(list); }