资源描述
第十三章spring管理hibernate
Ø 学习目标
Ø 学习内容
在使用hibernate的过程中,我们体验到了把数据当成对象来处理的方便,但是仍然没有脱离从前使用jdbc时,打开连接关闭连接之类的重复操作。我们还是需要不停的打开session然后关闭,偶而在过程中还要处理一下事务。
而在有了spring 之后,我们这些复杂的重复劳动,终于可以解脱了。
Spring提供了对orm框架的支持,这其中当然也包括了hibernate,我们可以通过spring为hibernate提供数据源,管理映射对象,管理事务等。
先来做一个干扰性最小的集成方式,在本例中,hibernate的配置完全由自己完成,不依赖spring,只由spring管理session对象与事务处理。
创建实体对象User.java
package ch04.entity;
import java.io.Serializable;
public class User implements Serializable {
private Integer uid;
private String username;
private String password;
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
映射文件:
User.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"
<hibernate-mapping>
<class name="ch04.entity.User" table="usertable">
<id name="uid" type="java.lang.Integer">
<column name="uid" />
<generator class="native" />
</id>
<property name="username" type="java.lang.String"/>
<property name="password" type="java.lang.String"/>
</class>
</hibernate-mapping>
hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="connection.username">root</property>
<property name="connection.url">jdbc:mysql://127.0.0.1:3306/test?&useUnicode=true&characterEncoding=gb2312</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="myeclipse.connection.profile">mysql</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<mapping resource="ch04/entity/User.hbm.xml" />
</session-factory>
</hibernate-configuration>
UserDao.java
package ch04.dao;
import ch04.entity.User;
public interface UserDao {
boolean add(User u);
boolean del(User u);
User getUserByName(User u);
}
实现类,需要继承自org.springframework.orm.hibernate3.support.HibernateDaoSupport 类,以便于spring可以为本类对象注入sessionfactory对象。
UserDaoImpl.java
package ch04.dao.impl;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import ch04.dao.UserDao;
import ch04.entity.User;
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
public boolean add(User u) {
try {//得到操作模板
this.getHibernateTemplate().save(u);
return true;
} catch (DataAccessException e) {
logger.error(e);
return false;
}
}
public boolean del(User u) {
getSession().delete(u);
return false;
}
public User getUserByName(User u) {
List<User> ulist = (List<User>)
getHibernateTemplate().findByExample(u);
if (ulist.size() != 0)
return ulist.get(0);
else {
return null;
}
}
@Override
public String toString() {
return "测试";
}
}
配置文件:
spring-hibernate.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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<!-- 得到sessionfactory 对象 -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation"
value="classpath:ch04/hibernate.cfg.xml">
</property>
</bean>
<!-- 为dao注入sessionfactory -->
<bean id="userDao" class="ch04.dao.impl.UserDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- 管理事务 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- 通知(增强) -->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
<!-- 详细见readme.txt
<tx:method name="add*" propagation="SUPPORTS" rollback-for="java.lang.Exception"/>
-->
</tx:attributes>
</tx:advice>
<!-- 接入点 -->
<aop:config>
<aop:pointcut expression="execution(* ch04.dao..*.*(..))" id="cut" />
<aop:advisor advice-ref="txadvice" pointcut-ref="cut" />
</aop:config>
</beans>
在配置中, 用<aop:…>标签管理了事务的关注点,这在上次学习中已经给大家做过介绍,重点讲解一下execution的表达方式,要注意,这个方法签名定义切点的方式,支持的是方法:
execution(public * *(..))
所有公有的方法, 第一个*表示返回值 第二个表示方法名
execution(* *User(..))这里第一个星表示返回值类型
上面定义了关注所有以User结尾的方法
如:getUser() addUser() deleteUser()
execution(* ch04.dao.UserDao.*(..))
关注userdao接口定义的方法
execution(* ch04.dao.UserDao+.*(..))
关注userdao接口和子类的方法,注意,这里包括了UserDaoImpl中定义的方法
execution(* com..*.*Dao.find*(..))
关注所有com包中子包内后缀为Dao的类里,以find开头的方法
关于参数的定义execution(* add(..))
..表示的任意多个任意类型的参数
也可以用*来表示任意类型参数
如:
execution(* add(*,int))
execution(* add(String,..))第一个参数为String其它不限
除了上面对于相应的hibernate事务处理进行aop管理之外,还可以为事务进行更详细的配置,比如:
<!-- 管理事务 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- 通知(增强) -->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
<!--
这里可以指定方法名称的定义
如
<tx:method name="add*" propagation="SUPPORTS" rollback-for="java.lang.Exception"/>
propagation 事务的传播行为 :
required必需的
supports支持
never从不
....
read-only 事务是否是只读的
no- rollback-for 不回滚的异常
rollback-for回滚的异常,可以用,分开
-->
</tx:attributes>
</tx:advice>
测试类:
Test.java
package ch04.util;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import ch04.dao.UserDao;
import ch04.entity.User;
public class Test {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("ch04/spring-hibernate.xml");
UserDao ud=(UserDao) ac.getBean("userDao");
//加用户
User u=new User();
u.setUsername("admin");
// u.setPassword("aaa");
ud.add(u);
u=ud.getUserByName(u);
System.out.println(u.getUid()+":"+u.getUsername()+":"+u.getPassword());
}
}
运行结果:
Hibernate:
insert
into
usertable
(username, password)
values
(?, ?)
Hibernate:
select
this_.uid as uid0_0_,
this_.username as username0_0_,
this_.password as password0_0_
from
usertable this_
where
(
this_.username=?
)
1:admin:null
在上面的例子中,hibernate本身配置由自己完成,spring只起到辅助作用,帮助使用者完成了相应的sessionfactory、session及事务的管理。当然还有更深入的一些方式,比如我们可以省掉hibernate的配置文件,sessionfactory完全由spring提供。
其它部分基本一置,去掉hibernate.cfg.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:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
<!-- 为dao注入sessionfactory -->
<bean id="userDao" class="ch05.dao.impl.UserDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- 管理事务 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- 通知(增强) -->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- 接入点 -->
<aop:config>
<aop:pointcut expression="execution(* ch05.dao..*.*(..))"
id="cut" />
<aop:advisor advice-ref="txadvice" pointcut-ref="cut" />
</aop:config>
<bean id="dataSource"
class="mons.dbcp.BasicDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver">
</property>
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/test?&useUnicode=true&characterEncoding=gb2312">
</property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="mappingLocations">
<list>
<value>classpath:/ch05/entity/User.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="show_sql">true</prop>
<prop key="format_sql">true</prop>
</props>
</property>
</bean>
</beans>
省掉了hibernate的配置文件后,我们还可以继续省掉映射文件
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
<!-- 数据源配置 -->
<bean id="dataSource"
class="mons.dbcp.BasicDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver">
</property>
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/test?&useUnicode=true&characterEncoding=gb2312">
</property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- hibernate配置 注意不用实体的配置文件用到代理bean是不同的 -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<!-- 实体对象配置方式 -->
<property name="annotatedClasses">
<list>
<value>ch06.entity.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.SQLServerDialect
</prop>
<prop key="show_sql">true</prop>
<prop key="format_sql">true</prop>
</props>
</property>
</bean>
<!-- 为dao注入sessionfactory -->
<bean id="userDao" class="ch06.dao.impl.UserDaoHibImpl">
<property name="sf">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- 管理事务 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- 通知(增强) -->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- 接入点 -->
<aop:config>
<aop:pointcut expression="execution(* ch06.dao..*.*(..))"
id="cut" />
<aop:advisor advice-ref="txadvice" pointcut-ref="cut" />
</aop:config>
</beans>
可以直接指定相应的实体,省掉映射文件内容。
<property name="annotatedClasses">
<list>
<value>ch06.entity.User</value>
</list>
</property>
当然并不是不需要映射关联的说明,而是我们用注解的方式来替代映射文件。
User.java
package ch06.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.annotations.Check;
@Entity(name="usertable")
public class User implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="uid")
private Integer uid;
@Column(name="username")
private String username;
@Column(name="password")
private String password;
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
完成上述内容之后,我们可以把hibernate的配置文件和映射文件全都省掉,工程中完全由spring进行管理。
补充:在得到sessionfactory对象时,我们需要为其注入一个数据源(dataSource) ,关于数据源的配置,spring也提供了多种支持方式:
下面的例子中,没有关于hibernate 的内容,只演示不同的数据源获取方式:
User.java
package ch07.entity;
public class User {
private Integer uid;
private String username;
private String password;
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
ret
展开阅读全文