一、在Spring中集成hibernate
1、hibernate简介:
hibernate是目前很流行的开源持久化框架。不仅提供了基本的对象关系映射,还提供了ORM工具所应具有的所有复杂功能,比如缓存、延迟加载、预先抓取以及分布式缓存。
2、声明hibernate的Session工厂
在Spring中,需要通过Spring的某一个Hibernate Session工厂bean来获取Hibernate SessionFactory。从3.1版本开始,Spring提供了三个Session工厂的Bean:
org.springframework.orm.hibernate3.LocalSessionFactoryBean
org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
org.springframework.orm.hibernate4.LocalSessionFactoryBean
对于以上三个Session工厂,选择方式如下:
①如果使用hibernate版本在3.2或更高版本(知道hibernate4.0,但不包含4.0),并且使用XML定义映射的话,就使用org.springframework.orm.hibernate3包中的LocalSessionFactoryBean。
②如果使用hibernate版本在3.2或更高版本(知道hibernate4.0,但不包含4.0),并且使用注解定义映射的话,就使用org.springframework.orm.hibernate3.annotation包中的AnnotationSessionFactoryBean。
③如果使用hibernate4,就使用org.springframework.orm.hibernate4.LocalSessionFactoryBean,这个Session工厂既可以匹配XML映射,也可以匹配注解映射。
3、在Spring中集成Hibernate的配置
先在web.xml中添加配置:
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
然后在Spring-dao.xml中配置SessionFactory(这里实体类使用注解映射):
<!-- 数据源连接池配置三种方式(推荐使用):DBCP、C3P0、BoneCP -->
<!-- DBCP配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
<property name="username" value="scott"></property>
<property name="password" value="scott"></property>
</bean>
<!-- 配置sessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="packagesToScan" value="com.mfc.entity"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop> <!--在控制台显示执行的数据库操作语句-->
<prop key="hibernate.format_sql">true</prop> <!--在控制台显示执行的数据哭操作语句(格式)-->
<prop key="hibernate.connection.autocommit">true</prop>
</props>
</property>
</bean>
使用Java配置SessionFactory:
@Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource){
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setPackagesToScan(new String[]{"com.mfc.entity"});
Properties properties = new Properties();
properties.setProperty("hibernate.show_sql", "true");
properties.setProperty("hibernate.format_sql", "true");
properties.setProperty("hibernate.connection.autocommit", "true");
return sessionFactory;
}
4、在dao层中使用SessionFactory:
以前经常使用HibernateTemplate,HibernateTemplate能够保证每个事务使用同一个Session,但是这种方式的弊端在于Repository实现会直接与Spring耦合。
先在的最佳实现是使用上下文Session,通过这种方式,会直接将Hibernate的SessionFactory装配到Repository中,并使用它来获取Session,程序如下:
package com.mfc.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.mfc.entity.Tuser;
@Repository(value = "tuserDao")
public class TuserDaoImpl implements TuserDao {
@Autowired
private SessionFactory sessionFactory;
private Session getSession(){
return sessionFactory.getCurrentSession();
}
@Override
public void add(Tuser tuser) {
getSession().save(tuser);
}
@Override
public void delete(Tuser tuser) {
getSession().delete(tuser);
}
@Override
public void update(Tuser tuser) {
getSession().update(tuser);
}
@Override
public List<Tuser> find(Tuser tuser) {
return getSession().createCriteria(Tuser.class).list();
}
@Override
public Tuser findByPrimary(String userId) {
return (Tuser) getSession().get(Tuser.class, userId);
}
}
二、Spring与Java持久化API
1、实体管理器工厂介绍
基于JPA的应用程序需要使用EntityManagerFactory的实现类来获取EntityManager实例。JPA定义了两种类型的实体管理器。
①应用程序管理类型:这种适用于不运行在Java EE容器中的独立应用程序,不做介绍
②容器管理类型:由JavaEE创建和管理,下面主要看这个。org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
2、使用容器管理类型的JPA
①在Spring容器中注入LocalContainerEntityManagerFactoryBean
<!-- DBCP配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
<property name="username" value="scott"></property>
<property name="password" value="scott"></property>
</bean>
<bean id="em" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"></property>
<property name="packagesToScan" value="com.mfc.entity"></property>
</bean>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="ORACLE"></property>
<property name="showSql" value="true"></property>
<property name="generateDdl" value="false"></property>
</bean>
②使用Java配置代替上面的配置:
@Bean
public BasicDataSource dataSource(){
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("");
dataSource.setUrl("");
dataSource.setUsername("");
dataSource.setPassword("");
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter){
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setJpaVendorAdapter(jpaVendorAdapter);
em.setPackagesToScan(new String[]{"com.mfc.entity"});
return em;
}
@Bean
public JpaVendorAdapter jpaVendorAdapter(){
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setDatabase("ORACLE");
jpaVendorAdapter.setShowSql(true);
jpaVendorAdapter.setGenerateDdl(false);
return jpaVendorAdapter;
}
③上面代码中的jpaVendorAdapter属性用于指明哪一个厂商的JPA实现,Spring提供了多个JPA厂商适配器:
EclipseLinkJpaVendorAdapter、HibernateJpaVendorAdapter、OpenJpaVendorAdapter、TopLinkJpaVendorAdapter(已废弃)
④上面配置中,注入HibernateJpaVendorAdapter时最终啊哟的是database属性,对应不同数据库,database属性的值不同。
数据库平台 | 属性database的值 |
IBM DB2 | DB2 |
Apache Derby | DERBY |
H2 | H2 |
Hypersonic | HSQL |
Informix | INFORMIX |
MySql | MYSQL |
oracle | ORACLE |
PostgresQL | POSTGRESQL |
Microsoft SQL Server | SQL SERVER |
Sybase | SYBASE |
3、从JNDI获取实体管理器工厂
xml配置:
<jee:jndi-lookup jndi-name="OracleConnection" id="emf"></jee:jndi-lookup>
<bean id="em" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="emf"></property>
</bean>
Java配置:
@Bean
public JndiObjectFactoryBean dataSource(){
JndiObjectFactoryBean factoryBean = new JndiObjectFactoryBean();
factoryBean.setJndiName("OracleConnection");
factoryBean.setProxyInterface(DataSource.class);
return factoryBean;
}
@Bean
public JndiObjectFactoryBean entityManagerFactory(){
JndiObjectFactoryBean em = new JndiObjectFactoryBean();
em.setJndiName("OracleConnection");
return em;
}
4、使用JPA编写Dao:
package com.mfc.dao;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;
import org.springframework.stereotype.Repository;
import com.mfc.entity.Tuser;
@Repository(value = "jpaTuserDao")
@Transactional
public class JPATuserDaoImpl implements TuserDao {
@PersistenceContext
private EntityManager em;
@Override
public void add(Tuser tuser) {
em.persist(tuser);
}
@Override
public void delete(Tuser tuser) {
em.remove(em.merge(tuser));
}
@Override
public void update(Tuser tuser) {
em.persist(em.merge(tuser));
}
@Override
public List<Tuser> find(Tuser tuser) {
String queryString = "select * from tuser";
Query query = em.createNativeQuery(queryString,Tuser.class);
List<?> result = query.getResultList();
List<Tuser> users = new ArrayList<Tuser>();
if (result !=null) {
Iterator<?> iterator =result.iterator();
while (iterator.hasNext()) {
Tuser user = (Tuser)iterator.next();
users.add(user);
}
}
return users;
}
@Override
public Tuser findByPrimary(String userId) {
return em.find(Tuser.class, userId);
}
}
三、借助SpringData实现自动化的JPA Repository
参考:https://blog.csdn.net/itguangit/article/details/78748077
https://blog.csdn.net/wu920604/article/details/52595999
以下值记录了Maven依赖和Spring注入配置,其他具体操作和介绍可以看上面参考的两篇博客。
1、这里注意Spring和Spring Data JPA的版本,我使用的Maven依赖:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.3.10.RELEASE</spring.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.oracle/ojdbc14 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>10.2.0.1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- springframework 4 dependencies begin -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring data jpa 数据库持久层 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.10.4.RELEASE</version>
</dependency>
<!-- springframework 4 dependencies end -->
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.11.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.11.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.javax.persistence/hibernate-jpa-2.0-api -->
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
</dependencies>
<build>
<finalName>SpringInAction7</finalName>
</build>
</project>
2、Spring-dao.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.8.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- DBCP配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
<property name="username" value="scott"></property>
<property name="password" value="scott"></property>
</bean>
<!-- 使用JPA实现持久化配置 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"></property>
<property name="packagesToScan" value="com.mfc.entity"></property>
</bean>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="ORACLE"></property>
<property name="showSql" value="true"></property>
<property name="generateDdl" value="false"></property>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- 测试:使用Spring Data构建自动化的JPA Repository ,com.mfc.SpringDataJPA是Repository接口的包名-->
<jpa:repositories base-package="com.mfc.SpringDataJPA"></jpa:repositories>
</beans>