jdbc-jdbcTemplate-hibernate-jpa-springDataJpa系列(一)

#1 須要解決的疑惑java

目前jdbc、jdbcTemplate、hibernate、jpa、spring之間有或多或少的關係。在使用它們的時候有着各類各樣的配置,初學者很容易分不清到底各自都作了什麼事情,若是對本身要求高點,那就測試下下面幾個問題:mysql

  • jdbc的幾個主要對象是什麼?
  • jdbc的原生方式是什麼樣的?怎麼配置?怎麼使用事務?
  • jdbcTemplate又是如何封裝jdbc的?怎麼使用事務?
  • hibernate的幾個主要對象是什麼?
  • hibernate的原生xml方式是什麼樣的?註解方式是什麼樣?怎麼配置?怎麼使用事務?
  • 爲何會出現jpa?若是是你來設計,你該如何來設計jpa?同時事務又怎麼辦?
  • jpa的幾個主要對象是什麼?
  • jpa的原生的開發方式是什麼樣的?怎麼配置?怎麼使用事務?
  • spring爲了讓你們使用jpa更加方便,又作了哪些封裝?又如何把datasource加進來?這時候,其餘的orm又該如何集成?
  • spring爲了再進一步的封裝,產生spring-data-jpa,它的xml方式和註解方式又是什麼樣?它又是如何在前面的基礎上作封裝呢?

從上面能夠再進一步總結:git

  • 事務的發展歷程是什麼樣的?
  • 對數據庫的操做,xml方式和註解方式又是如何逐步簡化的?

#2 實驗案例spring

爲了完全搞清楚它們之間的關係,作了如下幾個案例:sql

  • spring-jdbc:jdbc的原生方式開發和事務的使用數據庫

  • spring-jdbcTemplate:使用spring封裝的JdbcTemplate開發和事務的使用api

  • spring-hibernate-xml: hibernate的原生xml方式開發微信

  • spring-hibernate-xml-tx:hibernate的原生xml方式的事務的使用session

  • spring-hibernate-annotation:hibernate的原生的註解方式開發app

  • spring-hibernate-annotation-tx:hibernate的原生的註解方式的事務的使用

  • spring-jpa-hibernate:jpa的原生xml方式開發和事務的使用

  • spring-springjpa-hibernate:jpa的spring集成方式開發和事務的使用

  • spring-springjpa-hibernate-multDataSource:多數據源下jpa與spring集成開發和事務的使用

  • spring-data-jpa-hibernate:spring-data-jpa方式開發和事務的使用

案例都是使用SpringMVC搭建的環境,主要是能夠在此基礎上方便開發。而學習過程的測試案例都是使用的是spring-test來進行測試的。

項目地址以下jdbc-hibernate-jpa-spring

#3 實驗案例的詳細說明:

##3.1數據庫和表的準備

全部的案例都使用的數據庫爲test,表名爲user,表user有id,name,age屬性,User類以下:

public class User {
	private Long id;
	private String name;
	private int age;
	//略
}

目前使用的hibenrate版本是最新的4.3.8.Final。

##3.2 jdbc開發和事務的使用

###3.2.1 項目地址

該案例是項目spring-jdbc

###3.2.2 項目配置和使用分析

第一步: 先註冊驅動類

Class.forName("com.mysql.jdbc.Driver");

第二步: 使用DriverManager來獲取鏈接Connection

Connection conn=DriverManager.getConnection(url, user, password);

第三步: 使用Connection來執行sql語句,以及開啓、回滾、提交事務

Connection conn=jdbcDao.getConnection();
	conn.setAutoCommit(false);
	try {
		PreparedStatement ps=conn.prepareStatement("insert into user(name,age) value(?,?)");
		ps.setString(1,user.getName());
		ps.setInt(2,user.getAge());
		ps.execute();
		conn.commit();
	} catch (Exception e) {
		e.printStackTrace();
		conn.rollback();
	}finally{
		conn.close();
	}

缺點:

  • 每次都是獲取一個鏈接,用完以後就釋放掉,應該是用完再放回去,等待下一次使用,因此應該使用鏈接池datasource
  • Connection、PreparedStatement這種操做很麻煩,不方便
  • 業務代碼和事務代碼相互交叉,都嵌套在try catch中,代碼很不美觀

針對上述問題,spring開發了JdbcTemplate來完成相應的封裝

##3.3 spring-jdbcTemplate開發和事務的使用

###3.3.1 項目地址

該案例是項目spring-jdbcTemplate

###3.3.2 項目配置

首先註冊dataSource,用於管理Connection,每次使用完Connection,仍舊放回鏈接池,等待下一次使用

<bean id="dataSource"   
    class="com.mchange.v2.c3p0.ComboPooledDataSource"   
    destroy-method="close">   
    <property name="driverClass">   
        <value>${jdbc.driverClass}</value>   
    </property>   
    <property name="jdbcUrl">   
        <value>${jdbc.url}</value>   
    </property>   
    <property name="user">   
        <value>${jdbc.user}</value>   
    </property>   
    <property name="password">   
        <value>${jdbc.password}</value>   
    </property>   
    <!--鏈接池中保留的最小鏈接數。-->   
    <property name="minPoolSize">   
        <value>${jdbc.minPoolSize}</value>   
    </property>   
    <!--鏈接池中保留的最大鏈接數。Default: 15 -->   
    <property name="maxPoolSize">   
        <value>${jdbc.maxPoolSize}</value>   
    </property>   
    <!--初始化時獲取的鏈接數,取值應在minPoolSize與maxPoolSize之間。Default: 3 -->   
    <property name="initialPoolSize">   
        <value>${jdbc.initialPoolSize}</value>   
    </property>   
</bean>

而後註冊jdbcTemplate,使用上述dataSource

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
	<property name="dataSource" ref="dataSource"></property>
</bean>

對於事務,要註冊對應的事務管理器,這裏使用的是dataSource,因此要使用DataSourceTransactionManager,下面能夠看到不一樣的事務管理器

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"></property>
</bean>

而後開啓註解式的事務配置,即開啓@Transactional的功能:

<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>

###3.3.3 項目使用分析

配置說完了,來看具體的業務代碼了:

@Repository
public class UserDao {

	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	@Transactional
	public void save(User user){
		jdbcTemplate.update("insert into user(name,age) value(?,?)",user.getName(),user.getAge());
	}
}

和以前的jdbc開發相比,就很是簡潔了,一行代碼就能夠搞定。

來詳細看下jdbcTemplate.update的執行過程,其實也是從dataSource中獲取Connection,而後使用PreparedStatement這樣的對象來完成對應的sql語句

源碼以下:

Connection con = DataSourceUtils.getConnection(getDataSource());
PreparedStatement ps = null;
try {
	Connection conToUse = con;
	if (this.nativeJdbcExtractor != null &&
			this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) {
		conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
	}
	ps = psc.createPreparedStatement(conToUse);
	applyStatementSettings(ps);
	PreparedStatement psToUse = ps;
	if (this.nativeJdbcExtractor != null) {
		psToUse = this.nativeJdbcExtractor.getNativePreparedStatement(ps);
	}
	T result = action.doInPreparedStatement(psToUse);
	handleWarnings(ps);
	return result;
}

咱們再來看看,它又是如何來實現事務功能的。首先咱們知道jdbcTemplate原理是就是對jdbc的封裝,要想實現事務的功能,也必須對Connection執行如下的事務代碼:

conn.commit();
conn.rollback();

咱們還知道一個重要信息就是: <font color=red>

  • jdbc中執行sql的Connection和執行事務功能的的Connection必須是同一個Connection

這是很是須要明確的一點,由於後面要實現業務代碼和事務代碼的分離,因此必需要確保分離以後的二者使用的是同一個Connection,不然事務是不起做用的。 </font>

而Spring的@Transactional背後,則是使用SpringAOP來對咱們的UserDao進行了代理。代理的方式有2種,jdk代理或者cglib代理。 如UserDao的實例是咱們要代理的對象,暫且稱做target

  • jdk代理針對那些實現了相應的接口的類,建立出的代理對象也是實現了一樣的接口,同時該代理對象包含一個target
  • cglib代理針對類均可以進行代理,建立出的代理對象是繼承了target類,同時該代理對象內部包含一個target

上述的具體細節見個人博客SpringAOP源碼分析系列

而咱們採用的事務註解配置是:

<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>

中採用的是proxy-target-class="true" 表示咱們要使用cglib來進行代理,因此咱們在使用UserDao的時候實際上是使用的代理對象,這個代理對象實際上是繼承了UserDao,同時內部包含一個UserDao的實例,以下所示:

咱們實際使用的UserDao

這個代理對象加入了事務攔截器TransactionInterceptor,能夠想象成在真正執行代理對象內部target的save方法時,代理對象已經在外部進行了一層try catch包裹,在執行save的過程當中,一旦發現異常,就使用transactionManager來進行事務的回滾。

而咱們使用的transactionManager是DataSourceTransactionManager,它對事物的回滾也是經過Connection的rollback方法來完成的,DataSourceTransactionManager的源碼以下:

@Override
protected void doRollback(DefaultTransactionStatus status) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
	Connection con = txObject.getConnectionHolder().getConnection();
	if (status.isDebug()) {
		logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
	}
	try {
		con.rollback();
	}
	catch (SQLException ex) {
		throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
	}
}

此時咱們知道了jdbcTemplate.update方法使用Connection來完成sql功能,事務的提交和回滾也是經過Connection來完成的,只有這兩個Connection是同一個Connection的時候,才能真正起到事務做用。jdbcTemplate.update方法使用Connection是經過DataSourceUtils來獲取的Connection,這個Connection是和當前線程綁定的,DataSourceTransactionManager進行事務的提交和回滾所使用的Connection也是和當前線程綁定的,因此他們是同一個Connection。具體的驗證比較麻煩,原理就是使用ThreadLocal策略,可自行查看源碼

jdbcTemplate只是簡化了開發,仍然使用手寫sql的方式來開發,沒有使用orm,接下來就看看orm框架hibernate

##3.4 Hibernate的原生xml方式開發和事務的使用

###3.4.1 項目地址

該案例是項目spring-hibernate-xml

###3.4.2 項目配置

hibernate的原生xml方式涉及到2種配置文件

  • hibernate.cfg.xml : 用於配置數據庫鏈接和方言等等

    <hibernate-configuration>
        <session-factory name="hibernateSessionFactory">
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/</property>
            <property name="hibernate.connection.username">root</property>
            <property name="hibernate.connection.password">ligang</property>
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
            <property name="hibernate.show_sql">true</property>
            <property name="hibernate.default_schema">test</property>
            <mapping resource="hibernate/mapping/User.hbm.xml"/>
        </session-factory>
    </hibernate-configuration>
  • User.hbm.xml:用於配置實體User和數據庫user表之間的關係

    <hibernate-mapping>
    	<class name="com.demo.entity.User" table="user">
    		<id name="id" column="id" type="long">
    			<generator class="identity"/>
    		</id>
    		<property name="name" column="name" type="string"/>
    		<property name="age" column="age" type="int"/>
    	</class>
    </hibernate-mapping>

而後就是怎麼使用hibernate原生的api來加載這兩個文件。

  • 加載hibernate.cfg.xml

    Configuration config=new Configuration();  
    config.configure("hibernate/base/hibernate.cfg.xml");  
    sessionFactory=config.buildSessionFactory();

    其中的文件路徑是classpath路徑下的hibernate/base/hibernate.cfg.xml。

    若是使用的是

    config.configure();

    則默認加載的是classpath路徑下的hibernate.cfg.xml文件

  • 加載User.hbm.xml(以下三種方式)

    • 1 直接在hibernate.cfg.xml文件中引入該文件

      如上述hibernate.cfg.xml方式

    • 2 使用代碼添加類

      config.addClass(User.class);

      這種方式會在User類所在路徑下尋找 User.cfg.xml文件

    • 3 使用代碼添加資源映射文件

      config.addResource("hibernate/mapping/User.cfg.xml");

      這種方式會在classpath路徑下尋找hibernate/mapping/User.cfg.xml。

注意,寫路徑的時候不要再寫classpath: 了。

###3.4.3 主要的對象

SessionFactory、Session、Transaction 這些都是hibernate的原生的對象

  • SessionFactory

    剛纔加載hibernate.cfg.xml配置文件就產生了這樣的一個session工廠,它負責建立session

  • Session

    簡單理解起來就是:Session和jdbc中一個Connection差很少,Session對Connection進行了封裝

  • Transaction

    是hibernate本身的事務對象接口定義,經過session能夠開啓一個事務,使用以下:

    Transaction tx=null;
    try {
    	tx=session.beginTransaction();  
        session.save(user);  
        tx.commit();  
    } catch (Exception e) {
    	if(tx!=null){
    		tx.rollback();
    	}
    }finally{
    	session.close();
    }

###3.4.4 具體的使用和事務分析

使用方式就是以下:

@Repository
public class HibernateDao {
	private SessionFactory sessionFactory;
	public HibernateDao(){  
        Configuration config=new Configuration();  
        config.configure("hibernate/base/hibernate.cfg.xml");  
        sessionFactory=config.buildSessionFactory();  
    }
	public Session openSession(){
		return sessionFactory.openSession();
	}
}

public class UserDao {
	@Autowired
	private HibernateDao hibernateDao;
	public void save(User user){
		Session session=hibernateDao.openSession();
		Transaction tx=null;
		try {
			tx=session.beginTransaction();  
	        session.save(user);  
	        tx.commit();  
		} catch (Exception e) {
			if(tx!=null){
				tx.rollback();
			}
		}finally{
			session.close();
		}
	}
}

先根據hibernate.cfg.xml配置文件來建立SessionFactory,而後咱們每次就能夠經過SessionFactory來獲取一個Session,而後經過Session來開啓一個事務Transaction,來回滾或者提交。

這裏其實對業務代碼和事務代碼作了必定的分離:

  • 業務代碼由Session來完成
  • 事務代碼由Transaction來完成

咱們就須要明確的一點就是,這兩個對象的Connection必須是同一個Connection。

對於這個Transaction是如何實現的呢?來看下Transaction接口的實現類:

JdbcTransaction、JtaTransaction、CMTTransaction

咱們來看下JdbcTransaction:

public class JdbcTransaction extends AbstractTransactionImpl {

	private Connection managedConnection;
	
	protected void doBegin() {
		try {
			if ( managedConnection != null ) {
				throw new TransactionException( "Already have an associated managed connection" );
			}
			managedConnection = transactionCoordinator().getJdbcCoordinator().getLogicalConnection().getConnection();
			wasInitiallyAutoCommit = managedConnection.getAutoCommit();
			if ( wasInitiallyAutoCommit ) {
				LOG.debug( "disabling autocommit" );
				managedConnection.setAutoCommit( false );
			}
		}
	}

	protected void doCommit() throws TransactionException {
		try {
			managedConnection.commit();
		}
		//略
	}

	protected void doRollback() throws TransactionException {
		try {
			managedConnection.rollback();
		}
		//略
	}

}

從其中能夠看到,JdbcTransaction內部也是擁有一個Connection的,事務的提交和回滾等操做都是經過這個Connection來完成的。而這個Connection來自於Session。因此他們也保證了業務代碼和事務代碼所使用的Connection是同一個Connection。

對於JtaTransaction,再也不詳細去說明,能夠參考下這兩篇文章:

##3.5 hibernate的原生xml方式與spring集成以及事務的使用

###3.5.1 項目地址

該該案例是項目spring-hibernate-xml-tx

###3.5.2 配置

其實上面已經說到Hibernate的事務,若是想使用spring的@Transactional來使業務代碼和事務代碼進行分離,能夠以下操做:

  • 第一步:註冊dataSource

    前一個項目使用的hibernate,並無使用dataSource。

    <bean id="dataSource"   
        class="com.mchange.v2.c3p0.ComboPooledDataSource"   
        destroy-method="close">   
        <property name="driverClass">   
            <value>${jdbc.driverClass}</value>   
        </property>   
        <property name="jdbcUrl">   
            <value>${jdbc.url}</value>   
        </property>   
        <property name="user">   
            <value>${jdbc.user}</value>   
        </property>   
        <property name="password">   
            <value>${jdbc.password}</value>   
        </property>   
        <!--鏈接池中保留的最小鏈接數。-->   
        <property name="minPoolSize">   
            <value>${jdbc.minPoolSize}</value>   
        </property>   
        <!--鏈接池中保留的最大鏈接數。Default: 15 -->   
        <property name="maxPoolSize">   
            <value>${jdbc.maxPoolSize}</value>   
        </property>   
        <!--初始化時獲取的鏈接數,取值應在minPoolSize與maxPoolSize之間。Default: 3 -->   
        <property name="initialPoolSize">   
            <value>${jdbc.initialPoolSize}</value>   
        </property>   
    </bean>
  • 第二步:使用spring的LocalSessionFactoryBean來建立SessionFactory

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mappingResources">
            <list>
                <value>hibernate/mapping/User.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.MySQLDialect
                hibernate.show_sql=true
            </value>
        </property>
    </bean>

    這種建立方式至關於前面的經過核心配置文件hibernate.cfg.xml來建立SessionFactory的方式。

    一樣有數據庫的鏈接信息和hibernate的其餘的一些設置,只不過數據庫鏈接信息交給了dataSource。

  • 第三步:註冊hibernate的事務管理器 HibernateTransactionManager

    <bean id="transactionManager" 	class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    HibernateTransactionManager依賴於上述sessionFactory

  • 第四步:啓用spring的@Transactional的註解支持

    <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>

    使用上述的事務管理器

###3.5.3 使用和事務分析

@Repository
public class UserDao {

	@Autowired
	private SessionFactory sessionFactory;
	
	@Transactional
	public void save(User user){
		//Session session=sessionFactory.openSession();
		Session session=sessionFactory.getCurrentSession();
        session.save(user);  
        throw new RuntimeException();
	}
}

sessionFactory.openSession()是新開啓一個session,sessionFactory.getCurrentSession()是獲取當前線程綁定的session,只不過這時候必須使用sessionFactory.getCurrentSession()才能使事務有效,仍是爲了保證業務代碼中使用的session和事務代碼中使用的session是同一個session(這樣的話,就能夠保證他們使用的connection是同一個connection)。

因此這裏須要進一步封裝,使得用戶獲取session的時候,都是經過sessionFactory.getCurrentSession()來獲取的

來詳細瞭解下save方法的整個前先後後:

  • 1 在執行save方法以前,使用了HibernateTransactionManager開啓了相應的事務

    • 1.1 先使用sessionFactory的openSession()來建立一個session
    • 1.2 使用這個的session從dataSource中獲取了一個connection
    • 1.3 使用session的getTransaction方法開啓了一個Hibernate的一個Transaction事務
    • 1.4 把這個connection綁定到了當前線程
    • 1.5 把當前session綁定到當前線程

    源碼以下:

    protected void doBegin(Object transaction, TransactionDefinition definition) {
    HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
    Session session = null;
    try {
    	if (txObject.getSessionHolder() == null || txObject.getSessionHolder	
    				().isSynchronizedWithTransaction()) {
    		//1.1 先使用sessionFactory的openSession()來建立一個session
    		Interceptor entityInterceptor = getEntityInterceptor();
    		Session newSession = (entityInterceptor != null ?
    				getSessionFactory().withOptions().interceptor(entityInterceptor)
    				.openSession() :
    				getSessionFactory().openSession());
    		txObject.setSession(newSession);
    	}
    	session = txObject.getSessionHolder().getSession();
    	if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
    		//1.2 使用這個的session從dataSource中獲取了一個connection
    		Connection con = ((SessionImplementor) session).connection();
    		Integer previousIsolationLevel = DataSourceUtils.
    			prepareConnectionForTransaction(con, definition);
    		txObject.setPreviousIsolationLevel(previousIsolationLevel);
    	}
    	Transaction hibTx;
    	int timeout = determineTimeout(definition);
    	if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
    		//1.3 使用session的getTransaction方法開啓了一個Hibernate的一個Transaction事務
    		hibTx = session.getTransaction();
    		hibTx.setTimeout(timeout);
    		hibTx.begin();
    	}
    	else {
    		// Open a plain Hibernate transaction without specified timeout.
    		hibTx = session.beginTransaction();
    	}
    
    	// Add the Hibernate transaction to the session holder.
    	txObject.getSessionHolder().setTransaction(hibTx);
    
    	// Register the Hibernate Session's JDBC Connection for the DataSource, if set.
    	if (getDataSource() != null) {
    		//1.4 把這個connection綁定到了當前線程
    		Connection con = ((SessionImplementor) session).connection();
    		ConnectionHolder conHolder = new ConnectionHolder(con);
    		TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
    		txObject.setConnectionHolder(conHolder);
    	}
    	// Bind the session holder to the thread.
    	if (txObject.isNewSessionHolder()) {
    		//1.5 把當前session綁定到當前線程
    		TransactionSynchronizationManager.bindResource(
    			getSessionFactory(), txObject.getSessionHolder());
    	}
    	txObject.getSessionHolder().setSynchronizedWithTransaction(true);
    }

    }

  • 2 咱們經過使用sessionFactory.getCurrentSession()就獲取到了當前線程綁定的session,就是上述方式建立的session

  • 3 使用session來持久化user

  • 4 當拋出異常的時候,獲取與當前線程綁定的sessiion,再獲取其事務,就是步驟1中建立的事務,使用該事務進行回滾操做

    源碼以下:

    protected void doRollback(DefaultTransactionStatus status) {
    	HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
    	try {
    		txObject.getSessionHolder().getTransaction().rollback();
    	}
    }

##3.6 hibernate的原生註解方式開發和事務的使用

有了xml方式的經驗後,就很容易理解註解方式了,不一樣點就是前者以實體映射的xml文件告訴sessionFactory,後者以類所在的包的形式告訴sessionFactory,因此能夠參考Hibernate的原生xml方式開發和事務的使用

###3.6.1 項目地址

###3.6.2 配置

註解方式,就是把User實體的映射文件,改爲註解配置,以下:

@Entity
@Table(name="user")
public class User {

	@Id
	@GeneratedValue
	private Long id;
	private String name;
	private int age;
}

這裏的註解用的是javax.persistence包中的註解。而後就是如何讓hibernate知道User是一個實體呢?在hibernate的核心配置文件中hibernate.cfg.xml,這樣來聲明,使用mapping class:

<hibernate-configuration>
    <session-factory name="hibernateSessionFactory">
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.password">ligang</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.default_schema">test</property>

        <mapping class="com.demo.entity.User"/>

    </session-factory>
</hibernate-configuration>

##3.7 hibernate的註解方式開發與Spring集成和事務的使用

能夠參考參考hibernate的原生xml方式與spring集成以及事務的使用

###3.7.1 項目地址

###3.7.2 配置與使用

參考hibernate的原生xml方式與spring集成以及事務的使用

他們的不一樣點仍是將User實體告訴sessionFactory的方式不一樣,以下:

  • xml方式:

    <bean id="sessionFactory"        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="mappingResources">
            <list>
                <value>hibernate/mapping/User.hbm.xml</value>
            </list>
        </property>
     	//其餘略
    </bean>
  • 註解方式:

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="packagesToScan">
            <list>
            	<value>com.demo.entity</value>
            </list>
        </property>
       	//其餘略
    </bean>

#4 未完待續

內容不少了,下一篇文章再介紹

歡迎關注微信公衆號:乒乓狂魔

微信公衆號

相關文章
相關標籤/搜索