spring与hibernate的整合目的就是为了让 IOC 容器来管理 Hibernate 的核心接口SessionFactory以及让 Hibernate 使用上 Spring 的声明式事务来进行事务操作.
【1】Hibernate使用XML方式与Spring整合
即,Model上面不添加注解,使用*.hbm.xml方式与数据库进行关联。
① applicationContext.xm:
<?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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <!-- 导入资源文件 --> <context:property-placeholder location="classpath:db.properties"/> <context:component-scan base-package="com"></context:component-scan> <!-- 配置 C3P0 数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property> <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property> </bean> <!-- 配置 SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="configLocation" value="classpath:hibernate.cfg.xml"></property> <!-- 如果不想使用额外的hibernate.cfg.xml,则需要进行如下设置 --> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> </props> </property> <property name="mappingLocations" value="classpath:com/jane/ssh/entities/*.hbm.xml"></property> </bean> <!-- 这里配置与MyBatis整合Spring很类似 --> <!-- 配置 Spring 的声明式事务 --> <!-- 1. 配置 hibernate 的事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- 2. 配置事务属性 --> <!-- 配置哪些方法要加入事务控制 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 让所有的方法都加入事务管理,为了提高效率,可以把一些查询之类的方法设置为只读事务 --> <tx:method name="*" propagation="REQUIRED" read-only="true"/> <!-- 以下方法都是可能涉及写改的方法,就无法设置为只读 --> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="del*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="save*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 3. 配置事务切入点, 再把事务属性和事务切入点关联起来 --> <aop:config> <aop:pointcut expression="execution(* com.jane.ssh.service.*.*(..))" id="txPointcut"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> </aop:config> <!-- 开启HibernateTemplate,并且为其注入SessionFactory 使用HibernateTemplate不太方便的就是要获取session得通过getSessionFactory()方法获取 注意:这里之所以配置这个是因为Dao继承了HibernateDaoSupport --> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"/> </bean> </beans>
② hibernate.cfg.xml
由于数据源,*.hbm.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> <!-- 配置 hibernate 的基本属性 --> <!-- 方言 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> <!-- 是否显示及格式化 SQL --> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <!-- 生成数据表的策略 --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 启用二级缓存 --> <property name="cache.use_second_level_cache">true</property> <!-- 配置使用的二级缓存的产品 --> <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <!-- 配置启用查询缓存 --> <property name="cache.use_query_cache">true</property> </session-factory> </hibernate-configuration>
【2】Hibernate注解版与Spring整合
即,Model上面添加注解,此时不再存在*.hbm.xml。
① 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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <!-- 导入资源文件 --> <context:property-placeholder location="classpath:db.properties"/> <context:component-scan base-package="com"></context:component-scan> <!-- 配置 C3P0 数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property> <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property> </bean> <!-- 配置 SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> </props> </property> <!-- 如果实体类使用了注解,通常会使用如下方式 通过扫描包方式设置Spring取哪个包查找相应的实体类 --> <property name="packagesToScan"> <value>com.jane.ssh.entities</value> </property> --> </bean> <!-- 配置 Spring 的声明式事务 --> <!-- 1. 配置 hibernate 的事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- 2. 配置事务属性 --> <!-- 配置哪些方法要加入事务控制 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 让所有的方法都加入事务管理,为了提高效率,可以把一些查询之类的方法设置为只读事务 --> <tx:method name="*" propagation="REQUIRED" read-only="true"/> <!-- 以下方法都是可能涉及写改的方法,就无法设置为只读 --> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="del*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="save*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 3. 配置事务切入点, 再把事务属性和事务切入点关联起来 --> <aop:config> <aop:pointcut expression="execution(* com.jane.ssh.service.*.*(..))" id="txPointcut"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> </aop:config> <!-- 开启HibernateTemplate,并且为其注入SessionFactory 使用HibernateTemplate不太方便的就是要获取session得通过getSessionFactory()方法获取 注意:这里之所以配置这个是因为Dao继承了HibernateDaoSupport --> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"/> </bean> </beans>
② hibernate.cfg.xml
由于数据源,*.hbm.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> <!-- 配置 hibernate 的基本属性 --> <!-- 方言 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> <!-- 是否显示及格式化 SQL --> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <!-- 生成数据表的策略 --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 启用二级缓存 --> <property name="cache.use_second_level_cache">true</property> <!-- 配置使用的二级缓存的产品 --> <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <!-- 配置启用查询缓存 --> <property name="cache.use_query_cache">true</property> </session-factory> </hibernate-configuration>
当然,通常情况下,会去掉hibernate.cfg.xml,而将Hibernate相关属性配置在sessionFactory中。
③ 常见的Hibernate注解示例
package domain; import java.io.Serializable; import java.util.Date; import java.util.LinkedList; import java.util.List; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import javax.persistence.*; @Entity @Table(name="article_inf") @Cache(usage=CacheConcurrencyStrategy.READ_WRITE) public class Article implements Serializable{ private static final long serialVersionUID = 48L; @Id @Column(name="article_id") @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; @ManyToOne(targetEntity=Login.class) @JoinColumn(name="user_id",referencedColumnName="user_id",nullable=false) private Login login; @Column(name="boss_id") private Integer bossId; @Temporal(TemporalType.TIMESTAMP) @Column(name="create_date") private Date createDate; @Temporal(TemporalType.TIMESTAMP) @Column(name="modify_date") private Date modifyDate; @Column(name="article_authority") private Integer authority; @Column(name="title") private String title; @Column private String writer; @ElementCollection(targetClass=String.class) @CollectionTable(name="art_content",joinColumns=@JoinColumn(name="article_id",nullable=false)) @Column(name="content",length=5000) @OrderColumn(name="No_") private List<String> contents=new LinkedList<>(); @OneToMany(targetEntity=ArticlePictures.class,orphanRemoval=true,mappedBy="article",cascade=CascadeType.ALL) private List<ArticlePictures> pictures=new LinkedList<>(); @OneToMany(targetEntity=ArticleComments.class,orphanRemoval=true,mappedBy="article",cascade=CascadeType.ALL) private List<ArticleComments> comments=new LinkedList<>(); @OneToMany(targetEntity=ArticleVisitors.class,orphanRemoval=true,mappedBy="article",cascade=CascadeType.ALL) private List<ArticleVisitors> visitors=new LinkedList<>(); @OneToMany(targetEntity=ArticleCharm.class,orphanRemoval=true,mappedBy="article",cascade=CascadeType.ALL) private List<ArticleCharm> charm=new LinkedList<>(); //id public void setId(Integer id){ this.id=id; } public Integer getId(){ return id; } //login public void setLogin(Login login){ this.login=login; } public Login getLogin(){ return login; } //bossId public void setBossId(Integer bid){ this.bossId=bid; } public Integer getBossId(){ return bossId; } //createDate public void setCreateDate(Date date){ this.createDate=date; } public Date getCreateDate(){ return createDate; } //modifyDate public void setModifyDate(Date date){ this.modifyDate=date; } public Date getModifyDate(){ return modifyDate; } //authority public void setAuthority(Integer author){ this.authority=author; } public Integer getAuthority(){ return authority; } //title public void setTitle(String title){ this.title=title; } public String getTitle(){ return title; } //writer public void setWriter(String writer){ this.writer=writer; } public String getWriter(){ return writer; } //contents public void setContents(List<String> con){ this.contents=con; } public List<String> getContents(){ return contents; } //pictures public void setPictures(List<ArticlePictures> pic){ this.pictures=pic; } public List<ArticlePictures> getPictures(){ return pictures; } //comments public void setComments(List<ArticleComments> coms){ this.comments=coms; } public List<ArticleComments> getComments(){ return comments; } //visitors public void setVisitors(List<ArticleVisitors> visitors){ this.visitors=visitors; } public List<ArticleVisitors> getVisitors(){ return visitors; } //charm public void setCharm(List<ArticleCharm> charm){ this.charm=charm; } public List<ArticleCharm> getCharm(){ return charm; } }
至于Hibernate注解有哪些,注解如何使用,请参考系列博文:Spring Data JPA那些事。毕竟,JPA的默认实现就是Hibernate。