2015-04-01 38 views
2

我的用例如下: 創建應用程序用戶(EntityManager.persist)時,我還必須創建一個數據庫用戶並授予他特權(這就是爲什麼我需要hibernate nativeQuery)。原生查詢executeUpdate似乎在Spring事務中提交數據

我有一個Spring @Transactional方法,它調用吾道有兩個電話:

@Transactional 
public Integer createCompany(Company company) throws Exception { 
    companyDao.createReportUser(ReportUser user); 
    ... 
} 

吾道方法是這樣的:一旦

getEm().persist(companyReportsUser); 
getEm().createNativeQuery("CREATE USER [email protected] IDENTIFIED BY :password").setParameter("password", password).executeUpdate(); 
getEm().createNativeQuery("GRANT SELECT ON appdb.v_company TO [email protected]").executeUpdate(); 
//several grants 

現在,與第一線executeUpdate()被執行我可以在數據庫中看到持久的companyReportsUser和數據庫用戶(user1 @ localhost)。

所有nativeQueries都會被執行並立即提交。由於它們被提交,它們不能被回滾。 有沒有自動提交參數設置在我的配置中的任何地方,所以我假設它是'假'在Hibernate文檔中找到。

  1. 我測試過@Transactional行爲,而本機查詢和它的作品如應該(事務回滾當我拋出一個RuntimeException的,沒有數據被插入到數據庫)

  2. 調試時我」我們已經看到持久化操作在正在運行的事務中調用時會延遲執行。

  3. 本地查詢似乎產生了,並立即執行PreparedStatement(至少我沒有發現任何類型的隊列。

  4. 我想,我可能無法得到的相互作用之間休眠本地查詢和Spring的事務,但我花了我的時間閱讀關於交易和原生查詢的Spring和Hibernate文檔,並沒有發現任何可以幫助我的文檔。

  5. 也許有更好的方法來創建數據庫用戶並授予特權(雖然我沒有找到)

下面是我的應用程序配置:

的applicationContext.xml

<tx:annotation-driven transaction-manager="txManager" /> 

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory"> 
     <ref local="entityManagerFactory" /> 
    </property> 
</bean> 

<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="persistenceUnitName" value="domainPU" /> 
    <property name="loadTimeWeaver"> 
     <bean 
      class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" /> 
    </property> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> 
    </property> 
</bean> 

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="${db.url}" /> 
    <property name="username" value="${db.user.name}" /> 
    <property name="password" value="${db.user.password}" /> 
    <property name="validationQuery" value="select 1 as dbcp_connection_test" /> 
    <property name="testOnBorrow" value="true" /> 
</bean> 

的persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> 
<persistence-unit name="domainPU" transaction-type="RESOURCE_LOCAL"> 

    <provider>org.hibernate.ejb.HibernatePersistence</provider> 

    <class>com.domain.Entity1</class> 
    .... 

    <exclude-unlisted-classes>true</exclude-unlisted-classes> 

    <properties> 
     <property name="hibernate.show_sql" value="true" /> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> 
     <property name="hibernate.jdbc.batch_size" value="100"></property> 
     <property name="hibernate.order_inserts" value="true"></property> 
     <property name="hibernate.order_updates" value="true"></property> 

     <property name="hibernate.c3p0.min_size" value="5"></property> 
     <property name="hibernate.c3p0.max_size" value="30"></property> 
     <property name="hibernate.c3p0.timeout" value="300"></property> 
     <property name="hibernate.c3p0.max_statements" value="100"></property> 
     <property name="hibernate.c3p0.idle_test_period" value="${hibernate.c3p0.idle_test_period}"></property> 
    </properties> 
</persistence-unit> 

圖書館使用:

  • 休眠4.1.6.FINAL
  • 彈簧3.2.2.RELEASE
  • MySQL的連接器的Java-5.1.21
  • 的MySQL 5。5

回答

2

更深的挖掘交易在MySQL中是如何工作後,我找到了答案:

問題是在原生SQL查詢中的特定語句。

從MySQL文檔:

13.3.3語句造成隱式提交定義

  • 數據定義語言(DDL)語句或修改數據庫對象(... CREATE TABLE, DROP DATABASE ...)

  • 隱式使用或修改mysql數據庫中的表的語句(CREATE USER,DROP US ER和重命名用戶...,GRANT,REVOKE,...)

  • ...

更多細節在這裏:

http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html

我已決定將該行爲分爲兩部分:

  • 普通休眠語句(在事務內),
  • 本地查詢語句

和供應用戶用工具/動作來重新調用第二部分的情況下,出問題的時候。

其他解決方案將遷移到某些其他支持DDL操作周圍事務的RDBMS。

相關問題