2012-07-17 103 views
0

我創建了一個基本的Spring MVC/JPA/Hibernate應用程序。我正在嘗試保存一個UserProfile實體來測試是否可以實際保留它,但沒有保存,也沒有引發異常。Spring JPA不存儲實體

在控制器方法中,我創建了一個簡單的UserProfile(這是一個@Entity),然後我將它發送給一個服務方法。 UserProfileServiceImpl類用@Service註釋,addUserProfile(UserProfile配置文件)方法用@Transactional註釋。

在服務方法中,我所做的只是調用一個DAO方法(用@Repository註解的類)。在DAO方法中,我所做的就是調用entityManager.persist(object),其中object是用戶配置文件對象。

  • 沒有寫入服務器日誌,日誌級別位於INFO。
  • 沒有出現在Mysql查詢日誌中(我知道查詢日誌有效)
  • entityManager得到正確的注入。
  • 數據源正確啓動,因爲當我輸入錯誤的憑據時,我得到了SQLExceptions。

我希望你能告訴我什麼是錯的。我將在下面發佈我的一些代碼和配置文件。

服務方法:

// The service method gets called from the controller. 
// Its class is annotated with @Service 

@Transactional(readOnly = false) 
public void addUserProfile(UserProfile userProfile) { 
    userProfileDao.save(userProfile); 
} 

在DAO方法:

// The save(T object) method is in the GenericDaoJpa class, which is the superclass 
// of the UserProfileDaoJPA class that is referenced from the service. 
// I have established that the entityManager is there and the object is a 
// UserProfile. The @Repository annotation is on the child class UserProfileDaoJpa. 

public void save(T object) { 
    entityManager.persist(object); 
} 

主要應用-context.xml中

<context:property-placeholder location="classpath*:**/*.properties"/> 
<import resource="spring-jpa.xml"/> 

於應用程序的上下文web.xml文件

<mvc:annotation-driven /> 
<context:component-scan base-package="nl.codebasesoftware.produx" /> 

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <property name="prefix" value="/WEB-INF/views/"/> 
    <property name="suffix" value=".jsp"/> 
</bean> 

彈簧jpa.xml

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${db.driverClassName}" 
     p:url="${db.url}" p:username="${db.username}" p:password="${db.password}"/> 

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
     p:dataSource-ref="dataSource"/> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" 
     p:entityManagerFactory-ref="entityManagerFactory"/> 

<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/> 

<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"/> 

的persistence.xml

<persistence-unit name="mysqlPersistenceUnit" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <properties> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/> 
     <property name="hibernate.hbm2ddl.auto" value="create-drop"/> 
    </properties> 
</persistence-unit> 

<!-- Needed to properly process @PersistenceContext --> 
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> 

不知何故沒有SQL被髮送到MySQL這種設置,但也不例外要麼拋出,所以我不知道這是怎麼回事上。希望你能幫助:)

+0

其中休眠和你正在使用Spring版本? – 2012-07-18 05:55:02

+0

Spring 3.1.1和Hibernate 4.1.4 – Julius 2012-07-18 09:42:06

+0

剛纔我注意到,當我在DAO方法中的entityManager.persist()之後調用entityManager.flush()時,我得到以下錯誤: - 請求處理失敗;嵌套異常是javax.persistence.TransactionRequiredException:沒有事務正在進行。顯然沒有交易.... – Julius 2012-07-18 09:49:15

回答

2

我認爲你在服務中缺少事務傳播。標記readonly = false只是將會話設置爲自動刷新。但是設置適當的事務傳播將確保啓動trasaction和提交/回滾。

消除模式=「切面」,它已經開始工作,因爲我想是因爲每泉爲商務部

The default mode "proxy" will process annotated beans to be proxied using Spring's AOP framework (following proxy semantics, as discussed above, applying to method calls coming in through the proxy only). The alternative mode "aspectj" will instead weave the affected classes with Spring's AspectJ transaction aspect (modifying the target class byte code in order to apply to any kind of method call). AspectJ weaving requires spring-aspects.jar on the classpath as well as load-time weaving (or compile-time weaving) enabled. (See the section entitled Section 6.8.4.5, 「Spring configuration」 for details on how to set up load-time weaving.)

,也許你還沒有配置load time weaving

+0

我試過REQUIRED,REQUIRES_NEW和SUPPORTS無濟於事。 – Julius 2012-07-18 09:47:47

+1

從你已經提到的異常非常清楚,hibernate並沒有被破壞開始交易。 – 2012-07-18 09:55:39

+0

是真的......但是爲什麼?我認爲這與我在何處放置註釋和組件掃描等有關。我已將'@Transactional'註釋放在'@Service'類中的方法上。我也嘗試將@Transactional註釋放置在Dao('@ Repository')圖層中,但這也不起作用。我今天下午將重新創建我的設置文件,因爲我認爲它必須與組件掃描和我的註釋的位置有關。 – Julius 2012-07-18 10:24:28

0

好了之後,我知道了。首先,我想我找到了答案,在這裏

Declarative transactions (@Transactional) doesn't work with @Repository in Spring

但經過一些更多的測試,我發現這是不是

<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>

但其內容的位置。

刪除mode="aspectj"屬性後,它開始工作!如果有人想評論爲什麼,請做。

讓我與你分享我的完整設置。這是針對使用Hibernate 4的Spring 3.1的。注意:爲了簡潔,我只發佈了配置文件的內容,並省略了外部標籤<beans><persistence>以及命名空間聲明。我完全刪除了spring-jpa.xml,並將其內容移至application-context.xml中。

內容的web.xml的

<?xml version="1.0" encoding="ISO-8859-1" ?> 

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee  http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> 

<display-name>My Spring MVC web application</display-name> 

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>classpath*:**/application-context.xml</param-value> 
</context-param> 

<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 

<servlet> 
    <servlet-name>produxDispatcherServlet</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>classpath*:**/application-context-web.xml</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

<servlet-mapping> 
    <servlet-name>produxDispatcherServlet</servlet-name> 
    <url-pattern>/</url-pattern> 
</servlet-mapping> 
</web-app> 

內容應用程序的context.xml的:應用上下文-web.xml中的

<!-- main setup --> 
<context:property-placeholder location="classpath*:**/*.properties"/> 
<context:annotation-config/> 
<context:component-scan base-package="nl.codebasesoftware.produx.domain" /> 
<context:component-scan base-package="nl.codebasesoftware.produx.service" /> 
<context:component-scan base-package="nl.codebasesoftware.produx.dao" /> 
<!-- Data and JPA setup --> 
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${db.driverClassName}" 
     p:url="${db.url}" p:username="${db.username}" p:password="${db.password}"/> 
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource"/> 
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" p:entityManagerFactory-ref="entityManagerFactory"/> 
<tx:annotation-driven transaction-manager="transactionManager"/> 
<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"/> 

內容:

<mvc:annotation-driven /> 

<context:component-scan base-package="nl.codebasesoftware.produx.controller" /> 

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <property name="prefix" value="/WEB-INF/views/"/> 
    <property name="suffix" value=".jsp"/> 
</bean> 

內容的webapps/META-INF/persistence.xml

<persistence-unit name="mysqlPersistenceUnit" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <properties> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/> 
     <!-- <property name="hibernate.hbm2ddl.auto" value="create-drop"/> --> 
    </properties> 
</persistence-unit> 

<!-- Needed to properly process @PersistenceContext which injects the entity manager --> 
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> 

environment.properties的內容:

db.url=jdbc:mysql://localhost:3306/yourDatabaseName 
db.driverClassName=com.mysql.jdbc.Driver 
db.username=yourUsername 
db.password=yourPassword 
+0

看看我的編輯答案[鏈接](http:// static.springsource.org/spring/docs/2.5.x/reference/transaction.html) – 2012-07-19 08:32:55

+0

謝謝,那一定是問題所在 – Julius 2012-07-19 15:47:58