Spring實戰——使用物件-關係對映持久化資料
一、在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>