Spring温习(9)--配置hibernate信息
有时候为了为了操作方便,我们时常在spring整合hibernate的WEB项目中省去了用hibernate.cfg.xml的麻烦,将hibernate的信息直接配置在Spring配置文件中
下面的都是针对Spring整合Hibernate(注解方式的hibernate)来说的
?SH整合必须包
?其中spring必须包spring.jar和common-logging.jar
?? ? ?hibernate必须包hibernate.jar和六个其他必须包
?? ? ?剩下的就是用于数据连接的数据库连接包mysql.jar
?? ? ?用于注解的jpa.jar
?? ? ?用于连接池的c3p0.jar
?? ? ?用于测试的junit.jar
hibernate.cfg.xml和applicationContext.xml原始配置组合方式:
?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><!--这个只在DBScriptExport.java的new AnnotationConfiguration().configure()或者new Configuration().configure();这里面由于生成数据库表,或者通过config.buildSessionFactory都需要用到下面这四行关于数据库的配置.实际项目中,如果不适用到硬编码做这两件事,而是通过和Spring配合,那么这四行可以不写--><!--<property name="hibernate.current_session_context_class">thread</property><property name="connection.driver_class">com.mysql.jdbc.Driver</property><property name="connection.url">jdbc:mysql:///test</property><property name="connection.username">root</property> <property name="connection.password">root</property>--><property name="dialect">org.hibernate.dialect.MySQLDialect</property><property name="show_sql">true</property><property name="format_sql">true</property><!-- mapping类声明--><mapping /></session-factory></hibernate-configuration>
?
上面注释其实也没讲清楚,其实就是如果单独的hibernate项目来说,如果涉及到数据库操的任何操作代码,那么你必须配那段被注释掉的数据库连接信息,如果是整合Spring的话,那么就不用配置了,Spring提供了对hibernate支持的SessionFactory可以再注入后获取SESSION,然后你就可以任意去实现数据库操作了
?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" 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.5.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"><!-- 使用C3P0的连接池技术 --><bean id="dataSource" destroy-method="close"value="com.mysql.jdbc.Driver" /><property name="jdbcUrl" value="jdbc:mysql:///test" /><property name="user" value="root" /><property name="password" value="root" /><!-- 指定连接数据库连接池的最大连接数 --><property name="maxPoolSize" value="20" /><!-- 指定连接数据库连接池的最小连接数 --><property name="minPoolSize" value="1" /><!-- 指定连接数据库连接池的初始化连接数 --><property name="initialPoolSize" value="1" /><!-- 指定连接数据库连接池的连接的最大空闲时间 --><property name="maxIdleTime" value="20" /></bean><bean id="sessionFactory"value="classpath:hibernate.cfg.xml" /><!--那么这里给sessionFactory注入dataSource的解释:其实就是相当于单独的hibernate项目中使用config.buildSessionFactory()这样手动构建SessionFactory一样,必须提供有关数据库的参数配置信息也就是在hibernate.cfg.xm中 配置的数据库信息,这样使用session才能关联上数据库--><property name="dataSource" ref="dataSource" /></bean> <!--如果不配置SessionFactory,配置Spring自带的JdbcTemplate也挺好,然后注入到需要用到的类中去--><!--<bean id="jdbcTemplate"ref="dataSource" /> </bean>--><!--下面是Hibernate的事务管理器 ,如果是单独spring框架的项目中配置spring事务,那么就没有上边的sessionFactory而只会有dataSource,那么下面属性就不是sesionFactory而是DataSource了--><bean id="transactionManager"ref="sessionFactory" /></bean><!-- 启用注解方式的声明式事务支持 --><tx:annotation-driven transaction-manager="transactionManager" /><!-- =============================================== --><bean id="userDao" ref="sessionFactory" /></bean><bean id="sf" ref="userDao" /></bean></beans>
?? 当然这个配置中的sessionFactory是针对注解方式的配置的,如果是非注解方式的应该是:org.springframework.orm.hibernate3.LocalSessionFactoryBean
??上面关于SessionFactory注释说过了,如果不需要hibernate有关数据库的操作的话,那么就不要结合hibernate框架而是通过Spring自带的JdbcTemplate来进行数据库操作
不要hibernate.cfg.xml,将hibernate基本信息配置在applicatonContext.xm中
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" 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.5.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"><!-- 使用C3P0的连接池技术 --><bean id="dataSource" destroy-method="close"value="com.mysql.jdbc.Driver" /><property name="jdbcUrl" value="jdbc:mysql:///test" /><property name="user" value="root" /><property name="password" value="root" /><!-- 指定连接数据库连接池的最大连接数 --><property name="maxPoolSize" value="20" /><!-- 指定连接数据库连接池的最小连接数 --><property name="minPoolSize" value="1" /><!-- 指定连接数据库连接池的初始化连接数 --><property name="initialPoolSize" value="1" /><!-- 指定连接数据库连接池的连接的最大空闲时间 --><property name="maxIdleTime" value="20" /></bean><bean id="sessionFactory"/></property><property name="hibernateProperties"><props><prop key="dialect">org.hibernate.dialect.MySQLDialect </prop><prop key="format_sql">true</prop><prop key="show_sql">true</prop><prop key="cache.use_query_cache">true</prop><prop key="cache.provider_class">org.hibernate.cache.HashtableCacheProvider </prop><prop key="cache.provider_class">org.hibernate.cache.EhCacheProvider </prop></props></property> <!-- 针对xml而非注解方式的资源配置方式一 --> <!-- <property name="mappingResources"> <list><value>com/javacrazyer/domain/user.hbm.xml</value> </list></property> --><!-- 针对xml而非注解方式的资源配置方式二 --> <!--<property name="mappingLocations"> <list> <value>classpath:com/javacrazyer/domain/user.hbm.xml </value> </list></property>--><property name="annotatedClasses"><list><value>com.javacrazyer.domain.User</value></list></property></bean><!--下面是Hibernate的事务管理器 ,如果是单独spring框架的项目中配置spring事务,那么就没有上边的sessionFactory而只会有dataSource,那么下面属性就不是sesionFactory而是DataSource了--><bean id="transactionManager"ref="sessionFactory" /></bean><!-- 启用注解方式的声明式事务支持 --><tx:annotation-driven transaction-manager="transactionManager" /><!-- =============================================== --><bean id="userDao" ref="sessionFactory" /></bean><bean id="sf" ref="userDao" /></bean></beans>
?? ?关于上面两种配置hbm.xml文件的方式,如果文件有几十个的话,没必要多写出来可以写成通配符的样子,如下
<property name="mappingResources"> <list> <value>classpath:com/javacrazyer/**/*.hbm.xml</value> </list> </property>
??
注意与第一种方式不同的是applicatonContext.xml中只有sessionFactory发生了变化,数据源依旧注入到里面去,原来该配置hibernate.cfg.xml文件位置的配置现在换成了,众多行与第一种方式中hibernate.cfg.xml中类似的信息配置。
这样来说呢,更加省事些,当然我指的是SH结合的情况下,如果是hibernate单独的项目,必然用到new AnnotationConfiguration.config()就必然需要默认查找src下的hibernate.cfg.xml
用到的User.java
package com.javacrazyer.domain;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Table;@Entity@Table(name="user")public class User {@Id@GeneratedValueprivate Long id;private String username;private String pwd;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}public String toString(){return "id=" + id + ",username=" + username + ",pwd=" + pwd;}}
?
UserDao.java
package com.javacrazyer.dao;import java.io.Serializable;import java.util.List;import com.javacrazyer.domain.User;public interface UserDao {void add(User user);void delete(User user);void update(User user);User findById(Serializable id);List<User> findAll();}
?
UserDaoHibernateImpl.java
package com.javacrazyer.dao;import java.io.Serializable;import java.util.List;import org.hibernate.SessionFactory;import com.javacrazyer.domain.User;public class UserDaoHibernateImpl implements UserDao {private SessionFactory sessionFactory;public void setSessionFactory(SessionFactory sessionFactory) {this.sessionFactory = sessionFactory;}public void add(User user) {this.sessionFactory.getCurrentSession().save(user);}public void delete(User user) {this.sessionFactory.getCurrentSession().delete(user);}public List<User> findAll() {return (List<User>)this.sessionFactory.getCurrentSession().createQuery("from User").list();}public User findById(Serializable id) {return (User)this.sessionFactory.getCurrentSession().load(User.class, id);}public void update(User user) {user = (User)this.sessionFactory.getCurrentSession().merge(user);}}
门面服务类ServiceFacade .java
package com.javacrazyer.service;import java.util.List;import org.springframework.transaction.annotation.Isolation;import org.springframework.transaction.annotation.Transactional;import com.javacrazyer.dao.UserDao;import com.javacrazyer.domain.User;@Transactional(isolation=Isolation.READ_COMMITTED)public class ServiceFacade {//依赖的对象:主动去获取private UserDao userDao;public ServiceFacade(){}//构造器public ServiceFacade(UserDao userDao){this.userDao = userDao;}//set方法public void setUserDao(UserDao userDao){this.userDao = userDao;}public void addUser(User user){userDao.add(user);}@Transactional(readOnly=true)public User findById(Long id){return userDao.findById(id);}@Transactional(readOnly=true)public List<User> findAll(){return userDao.findAll();}}
?
?测试类HibernateTest .java
package com.javacrazyer.service.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.javacrazyer.domain.User;import com.javacrazyer.service.ServiceFacade;public class HibernateTest {@Testpublic void addUser(){ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");ServiceFacade sf = (ServiceFacade)context.getBean("sf");User user = new User();user.setUsername("test1");user.setPwd("test1");sf.addUser(user);System.out.println(user);}}
?
??
题外话:
针对第一种方式hibernate.cfg.xml中如果配置了数据库信息的,下面这两个类有必要看下
生成数据库脚本的DBScriptExport .java
package com.javacrazyer.dao;import java.sql.SQLException;import org.hibernate.cfg.AnnotationConfiguration;import org.hibernate.cfg.Configuration;import org.hibernate.tool.hbm2ddl.SchemaExport;import org.junit.Test;/** * 根据对象关系映射文件直接生成数据库表或生成建表的脚本 * * */public class DBScriptExport {@Testpublic void export2DB() {// 加载Hibernate的全局配置文件,config()默认传入src下面的hibernat.cfg.xml配置文件Configuration config = new AnnotationConfiguration().configure();SchemaExport export = new SchemaExport(config);export.create(true, true);}public static void export2File(String dest) {Configuration config = new AnnotationConfiguration().configure();SchemaExport export = new SchemaExport(config);export.setOutputFile(dest).setDelimiter(";").setFormat(true).create(true, false);}}
用于获取session的?HibernateUtils .java
package com.javacrazyer.dao;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.AnnotationConfiguration;import org.hibernate.cfg.Configuration;public class HibernateUtils {private static SessionFactory factory;private HibernateUtils() {}static {Configuration cfg = new AnnotationConfiguration().configure();factory = cfg.buildSessionFactory();}public static SessionFactory getSessionFactory() {return factory;}public static Session getSession() {return factory.getCurrentSession();}public static void closeSession(Session session) {if (session != null) {if (session.isOpen()) {session.close();}}}}
?
测试类.java
package com.javacrazyer.service.test;import org.hibernate.classic.Session;import org.junit.Test;import com.javacrazyer.dao.HibernateUtils;import com.javacrazyer.domain.User;public class HibernateTest {@Testpublic void testAdd(){//如果是getCurrentSession得配置一些代码Session session=(Session) HibernateUtils.getSession();User user = new User();user.setUsername("test1");user.setPwd("test1");session.save(user);}}
?
最后,关于这两种方式,根据个人喜好,我比较爱用第二种
?