java综合(四)spring与hibernate整合

完成例子:spring容器中取出业务bean,传入参数用户信息,持久化到数据库.

1.新建工程,导入spring包和hibernate包,还需要mysql驱动包,为方便测试,还导入junit包.


2.业务层类与dao层

package com.skymr.sphi.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import com.skymr.sphi.model.User;

public class UserDao {
	
	private SessionFactory sessionFactory;
	
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public void save(User user){
		System.out.println("执行UserDao save方法:");
		Session session = sessionFactory.openSession();
		Transaction tran = session.beginTransaction();
		session.save(user);
		tran.commit();
		session.close();
	}
	
	public void update(User user){
		System.out.println("执行UserDao update方法:");
		Session session = sessionFactory.openSession();
		Transaction tran = session.beginTransaction();
		session.update(user);
		tran.commit();
		session.close();
	}
	
	public void delete(int id){
		System.out.println("执行UserDao delete方法:");
		Session session = sessionFactory.openSession();
		Transaction tran = session.beginTransaction();
		session.delete(id);
		tran.commit();
		session.close();
	}
	
	public User query(int id){
		System.out.println("执行UserDao query方法:");
		Session session = sessionFactory.openSession();
		User ret = (User)session.get(User.class, id);
		session.close();
		return ret;
	}
}

package com.skymr.sphi.service;

import com.skymr.sphi.model.User;

public interface UserService {
	//保存用户信息
	public void save(User user);
	//更新用户信息
	public void update(User user);
	//删除用户信息
	public void delete(int id);
	//查询用户信息
	public User query(int id);
}

package com.skymr.sphi.service.impl;

import com.skymr.sphi.dao.UserDao;
import com.skymr.sphi.model.User;
import com.skymr.sphi.service.UserService;

public class UserServiceBean implements UserService{

	private UserDao userDao;
	
	public UserDao getUserDao() {
		return userDao;
	}

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	public void delete(int id) {
		userDao.delete(id);
	}

	public User query(int id) {
		return userDao.query(id);
	}

	public void save(User user) {
		userDao.save(user);
	}

	public void update(User user) {
		userDao.update(user);
	}

}

3.配置文件

1)spring主配置文件 config/applicationContext.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
	
	<!-- 导入hibernate配置,将原hibernate的一些配置放到spring中管理 -->
	<import resource="classpath*:config/spring_annotation-hibernate.xml"/>
	
	<bean id="userDao" class="com.skymr.sphi.dao.UserDao">
		<!-- 不知道为什么 不能注解注入,会报错 -->
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>
	<bean id="userService" class="com.skymr.sphi.service.impl.UserServiceBean">
		<!-- 不知道为什么 不能注解注入,会报错 -->
		<property name="userDao" ref="userDao"></property>
	</bean>
</beans>


知道使用注解注入失败的原因了,是因为没开启注解的原因.

开启注解

<context:annotation-config></context:annotation-config>  
要使用context标签就必须引入规范

<beans xmlns="http://www.springframework.org/schema/beans"    
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
    xmlns:context="http://www.springframework.org/schema/context"    
    xsi:schemaLocation="http://www.springframework.org/schema/beans     
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd    
 http://www.springframework.org/schema/context     
 http://www.springframework.org/schema/context/spring-context-2.5.xsd"> 



2)spring管理的hibernate配置config/spring_annotation-hibernate.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
	<!-- 数据源 -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<!-- 这个属性driverClassName为什么在DriverManagerDataSource及父类中找不到呢 -->
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://127.0.0.1:3306/website"/>
		<property name="username" value="root" />
		<property name="password" value="root" />
	</bean>
	<!-- sessionFactory配置 -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="hibernateProperties">
			<props>
                <!-- 设置Hibernate方言 -->  
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
                <!-- 是否打印sql -->  
                <prop key="hibernate.show_sql">true</prop>  
                <!-- 格式化sql -->  
                <prop key="hibernate.format_sql">true</prop>  
                <!-- 是否自动更新表 -->  
                <prop key="hibernate.hbm2ddl.auto">update</prop>  
                <prop key="hibernate.current_session_context_class">thread</prop>  
                <!-- 最大抓取深度,如果为0,则关闭默认的外连接抓取。建议值为0-3 -->  
                <prop key="hibernate.max_fetch_depth">1</prop>  
                <!-- 用于生成有助于调试的注释信息,默认为关闭 -->  
                <prop key="hibernate.use_sql_comments">true</prop>  
			</props>
		</property>
		<property name="configLocations">
			<list>
				<value>classpath*:config/hibernate/hibernate.cfg.xml</value>
			</list>
		</property>
	</bean>
	
</beans>

3)Hibernate自己的配置config/hibernate/hibernate.cfg.xml

<?xml version='1.0' encoding='UTF-8'?>  
<!DOCTYPE hibernate-configuration PUBLIC  
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  
<hibernate-configuration>  
    <session-factory>  
    	<!-- 原来的数据源,用户名,密码等配置都放到了spring中配置了,这里只需要配置映射 -->
        <!-- pojo映射配置,以前是一个配置文件***.hbm.xml,现在使用注解方法配置映射了 -->  
        <mapping class="com.skymr.sphi.model.User"/>  
    </session-factory>  
</hibernate-configuration>  

4.实体类及Hibernate注解映射

package com.skymr.sphi.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="test_user") //表名
public class User {

	@Id //指定主键
	@GeneratedValue
	private int id;
	
	@Column(length=32)
	private String userName;
	@Column(length=32)
	private String password;
	@Column(length=10)
	private int age;

	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;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
	
	
}

GeneratedValue:指定Id生成策略,默认是auto,就是@GeneratedValue(strategy = GenerationType.AUTO)


5.junit测试

package com.skymr.sphi.test;

import java.sql.SQLException;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.skymr.sphi.model.User;
import com.skymr.sphi.service.UserService;

public class TestMain {
	@Test  
	public void saveUserTest() throws SQLException{  
	    ApplicationContext context= new ClassPathXmlApplicationContext("/config/applicationContext.xml");  
	    UserService service =(UserService) context.getBean("userService");  
	      
	    User user = new User();  
	    user.setUserName("111");
	    user.setPassword("222");
	    user.setAge(10);
	    service.save(user);
	}  
}

经过测试,数据库中添加了test_user表,并成功添加一行数据.

6.spring管理Hibernate事务

上面例子中的UserDao类中使用的事务是直接写代码的方式,在session操作的前后进行事务的开始与结束,这里可以使用spring来管理事务了.

在spring_annotation-hibernate.xml配置中加入这段:

	<!-- spring管理hibernate事务 aop拦截,代理事务 -->
	<!-- 事务管理器 -->
	<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>
	
	<!-- 事务特性 ,使用时加载,抽象类 -->
	<bean id="transactionBean" 
		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
		lazy-init="true" 
		abstract="true">
		<property name="transactionManager" ref="transactionManager"></property>	
		<property name="transactionAttributes">
			<props>
				<prop key="add*">PROPAGATION_REQUIRED,-Exception</prop>
				<prop key="update*">PROPAGATION_REQUIRED,-Exception</prop>
				<prop key="delete*">PROPAGATION_NEVER</prop>
				<prop key="get*">PROPAGATION_REQUIRED,-Exception</prop>
			</props>
		</property>
	</bean>

transactionAttributes的各种属性的意义如下:


PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。 
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。 
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。 
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。 
PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

-Exception表示有Exception抛出时,事务回滚. -代表回滚+就代表提交 

readonly 就是read only, 设置操作权限为只读,一般用于查询的方法,优化作用.


经过以上配置后,spring就拦截了hibernate的数据库操作,对操作进行事务管理.

修改UserDao类,去掉代的事务代码

package com.skymr.sphi.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.skymr.sphi.model.User;

public class UserDao {
	
	private SessionFactory sessionFactory;
	
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public void save(User user){
		System.out.println("执行UserDao save方法:");
		Session session = sessionFactory.openSession();
		session.save(user);
		session.close();
	}
	
	public void update(User user){
		System.out.println("执行UserDao update方法:");
		Session session = sessionFactory.openSession();
		session.update(user);
		session.close();
	}
	
	public void delete(int id){
		System.out.println("执行UserDao delete方法:");
		Session session = sessionFactory.openSession();
		session.delete(id);
		session.close();
	}
	
	public User query(int id){
		System.out.println("执行UserDao query方法:");
		Session session = sessionFactory.openSession();
		User ret = (User)session.get(User.class, id);
		session.close();
		return ret;
	}
}


测试后出现异常:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in URL [file:/E:/webworkspace/spring_hibernate/WebRoot/WEB-INF/classes/config/spring_annotation-hibernate.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.hibernate.engine.spi.SessionFactoryImplementor.getConnectionProvider()Lorg/hibernate/service/jdbc/connections/spi/ConnectionProvider;

都是照着视频做的,没理由出错啊.

上网查找,发现是spring与hibernate版本不匹配的原因:

原因,在使用Spring3.2.x与Hibernate4.3.x(4.1.7以上)的版本整合时出的错。  

解决方案:把Hibernate降至4.1.7或以下的版本就行了。  
http://sourceforge.net/projects/hibernate/files/hibernate4/  
这是由Spring和Hibernate4.3.x版本兼容性的问题产生的  
它的官方有如下说明:  
https://jira.springsource.org/browse/SPR-10839  


于是下载hibernate 4.1.10,测试后正常.

7.UserDao调整

Dao层的Bean(UserDao)是个类,没有接口,是不规范的,spring中都要使用接口的,因为spring的底层的代理拦截(AOP原理)必须要有接口,我记得有另一种方法(动态代理)是不用代理的,既然spring这样要求,那就再加入个接口吧

package com.skymr.sphi.dao;

import com.skymr.sphi.model.User;

public interface UserDao {
	
	public void save(User user);
	
	public void update(User user);
	
	public void delete(int id);
	
	public User query(int id);
}
package com.skymr.sphi.dao.impl;

import javax.annotation.Resource;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.skymr.sphi.dao.UserDao;
import com.skymr.sphi.model.User;

public class UserDaoBean implements UserDao{
	
	@Resource
	private SessionFactory sessionFactory;
	

	public void save(User user){
		System.out.println("执行UserDao save方法:");
		Session session = sessionFactory.openSession();
		session.save(user);
		session.close();
	}
	
	public void update(User user){
		System.out.println("执行UserDao update方法:");
		Session session = sessionFactory.openSession();
		session.update(user);
		session.close();
	}
	
	public void delete(int id){
		System.out.println("执行UserDao delete方法:");
		Session session = sessionFactory.openSession();
		session.delete(id);
		session.close();
	}
	
	public User query(int id){
		System.out.println("执行UserDao query方法:");
		Session session = sessionFactory.openSession();
		User ret = (User)session.get(User.class, id);
		session.close();
		return ret;
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值