简述
将Hibernate的SessionFactory的创建交给Spring框架,将DAO也交给Spring框架,则可以由框架将它注入到DAO中。将业务逻辑层的业务类也交给Spring框架,以将DAO注入到业务逻辑类对象中。
处于Spring框架管理下的DAO的实现类不需要直接操作Session,Spring为其提供了HibernateDaoSupport
类作为父类,则继承下了一个getHibernateTemplate()
方法可以获得一个直接操作数据库的HibernateTemplate
类对象。
在Spring的管理下通过Spring自己的配置文件设定Hibernate的全局设置、注册ORM映射,则这些都在applicationContext.xml
中完成,Hibernate不再需要自己的hibernate.cfg.xml
和hibernate.properties
配置文件。
除了Hibernate和Spring本来的jar包之外,还需要这些包:
它们大多可以在mvnrepository和java2s这两个网站找到。
代码
User类的属性
private Integer id;
private String name;
private String password;
User.hbm.xml
User的ORM映射。
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="myPOJO">
<class name="User" table="USERTABLE">
<id name="id" column="ID" unsaved-value="null">
<generator class="native" />
</id>
<property name="name" column="USERNAME" type="string"
not-null="true" />
<property name="password" column="PASSWORD" type="string"
not-null="true" />
</class>
</hibernate-mapping>
UserDAO.java
数据访问控制,在这里使用了Spring框架为Hibernate提供的HibernateTemplate类简化操作。
package myDAO;
import java.util.List;
import myPOJO.User;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
//注意用的Hibernate4这里就导Hibernate4的,而不是3的
import org.springframework.orm.hibernate4.HibernateCallback;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;
//自己的DAO继承了Spring框架为Hibernate提供的HibernateDaoSupport类
@SuppressWarnings("unchecked")
public class UserDAO extends HibernateDaoSupport {
// 登录时调用的验证方法
public User login_A(String name, String password) {
// 书写hql语句
String hql = "from User where name=? and password=?";
// 获取HibernateTemplate对象,该对象具有操作数据库的常用方法,无需考虑Session
HibernateTemplate ht = this.getHibernateTemplate();
// 传入hql语句和'?'代换列表以做查询
List<User> ls_usr = (List<User>) ht.find(hql, name, password);
// 返回查询结果
return (null == ls_usr || ls_usr.isEmpty()) ? null : ls_usr.get(0);
}
// 登录时调用的验证方法(演示通过execute方法直接在Session上操作)
// 当所在的方法的参数需要被内部类里面使用时,该参数必须为final以让该引用不可改变
public User login_B(final String name, final String password) {
// 书写hql语句(hibernate 4.1之后需使用命名参数或JPA方式占位符才不报警告)
final String hql = "from User where name=?0 and password=?1";
// 获取HibernateTemplate对象
HibernateTemplate ht = this.getHibernateTemplate();
// 执行execute方法,传入HibernateCallback<T>接口
List<User> ls_usr = (List<User>) ht
.execute(new HibernateCallback<List<User>>() {
// 覆写其中的<T> doInHibernate方法,Session通过形参注入
@Override
public List<User> doInHibernate(Session sssn)
throws HibernateException {
// 用hql建立Query对象
Query qry = sssn.createQuery(hql);
// 设定?参数值(JPA方式设定参数要给数字加双引号)
qry.setParameter("0", name);
qry.setParameter("1", password);
// 查询并返回结果,不用考虑Session的开关
return qry.list();
}
});
// 在外部类中做判读并返回
return (null == ls_usr || ls_usr.isEmpty()) ? null : ls_usr.get(0);
}
}
UserService.java
业务逻辑层的类,组合了需要的DAO实现类。
package myService;
import myDAO.UserDAO;
import myPOJO.User;
//用户的业务类
public class UserService {
// 需要组合用户的UserDAO以使用
private UserDAO usr_d;
// 登录业务
public User login(String name, String password) {
return usr_d.login_B(name, password);
}
// 用于DI的getter和setter
public UserDAO getUsr_d() {
return usr_d;
}
public void setUsr_d(UserDAO usr_d) {
this.usr_d = usr_d;
}
}
Main.java
用于测试集成成功与否。
package myTest;
import myPOJO.User;
import myService.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
// 测试
public static void main(String[] args) {
// Spring上下文,载入Spring配置文件
ApplicationContext context = new ClassPathXmlApplicationContext(
"./applicationContext.xml");
// 获取一个业务处理的类的对象
UserService us = (UserService) context.getBean("userService");
// 调用登录方法
User usr = us.login("lzh", "sb");
System.out.println(usr.getId());
}
}
Write.java
用于写入数据库和向下建立DB表,这样才能做测试。它依赖了前面笔记里的HibernateUtils
,而且使用时要先加上两个Hibernate配置文件,建立完DB表再把他们都删去。
package myTest;
import myPOJO.User;
import myTools.HibernateUtils;
import org.hibernate.Session;
import org.hibernate.Transaction;
public class Write {
// 写入数据库
public static void main(String[] args) {
User usr = new User();
usr.setName("刘知昊");
usr.setPassword("sbsbsb");
// 获取Session对象
Session sssn = HibernateUtils.getSession();
// 开启事务
Transaction trnsctn = sssn.beginTransaction();
sssn.save(usr);
// 提交事务
trnsctn.commit();
// 关闭Session实例并且把ThreadLocal中的副本清除
HibernateUtils.closeSession();
}
}
applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<!-- 配置数据源(DB层),使用Apache的DBCP2数据源连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<!-- 指定连接数据库的驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!-- 指定连接数据库的URL -->
<property name="url" value="jdbc:mysql://localhost:3306/TEST_HBNT?useSSL=true&characterEncoding=utf8"/>
<!-- 指定连接数据库的用户名 -->
<property name="username" value="root"/>
<!-- 指定密码 -->
<property name="password" value="3838438"/>
</bean>
<!-- 配置SessionFactory为LocalSessionFactoryBean -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- 注入上面配置的数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 注入Hibernate设置(相当于hibernate.properties文件的功能) -->
<property name="hibernateProperties">
<props>
<!-- Hibernate方言类 -->
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<!-- 是否显示SQL -->
<prop key="hibernate.show_sql">
true
</prop>
</props>
</property>
<!-- 注入Hibernate的ORM映射(DO层)(相当于hibernate.cfg.xml文件的功能)-->
<property name="mappingResources">
<list>
<value>myPOJO/User.hbm.xml</value>
</list>
</property>
</bean>
<!-- 配置HibernateDaoSupport子类(DAO层) -->
<bean id="userDAO" class="myDAO.UserDAO">
<!-- HibernateDaoSupport总是需要注入前面的LocalSessionFactoryBean -->
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 配置业务逻辑的类(业务逻辑层) -->
<bean id="userService" class="myService.UserService">
<!-- 注入相应的DAO -->
<property name="usr_d" ref="userDAO"></property>
</bean>
<!-- 配置声明式事务 -->
<!-- 配置Hibernate事务管理器(HibernateTransactionManager) -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<!-- 注入前面的LocalSessionFactoryBean -->
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 事务增强,引用前面配置的Hibernate事务管理器 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- 事务切面 -->
<aop:config>
<aop:pointcut expression="execution(* myService.*.*(..))" id="txMethod" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txMethod"/>
</aop:config>
</beans>
运行结果
Hibernate: select user0_.ID as ID1_0_, user0_.USERNAME as USERNAME2_0_, user0_.PASSWORD as PASSWORD3_0_ from USERTABLE user0_ where user0_.USERNAME=? and user0_.PASSWORD=?
1