0

基本的なSpringMVC/ JPA/Hibernateアプリを作成しました。UserProfileエンティティを保存して、実際に永続化できるかどうかをテストしようとしていますが、何も保存されず、例外もスローされません。

コントローラメソッドで、単純なUserProfile(@Entity)を作成し、それをサービスメソッドに送信しています。UserProfileServiceImplクラスには@Serviceの注釈が付けられ、addUserProfile(UserProfile profile)メソッドには@Transactionalの注釈が付けられます。

serviceメソッドでは、DAOメソッド(@Repositoryで注釈が付けられたクラス)を呼び出すだけです。DAOメソッドでは、entityManager.persist(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"/>

application-context-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>

spring-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に送信されませんが、例外もスローされないため、何が起こっているのかわかりません。あなたが助けることができることを願っています:)

4

2 に答える 2

2

サービスでトランザクションの伝播が欠落していると思います。マーキング readonly=false は、セッションを自動フラッシュに設定するだけです。ただし、適切なトランザクションの伝播を設定すると、トランザクションの開始とコミット/ロールバックが確実になります。

mode="aspectj" を削除した後、春のドキュメントのように思うので、動作し始めました

デフォルトモードの「proxy」は、Spring の AOP フレームワークを使用してプロキシされるアノテーション付き Bean を処理します (上記で説明したように、プロキシのセマンティクスに従い、プロキシのみを介して着信するメソッド呼び出しに適用されます)。代わりに、代替モード「aspectj」は、影響を受けるクラスを Spring の AspectJ トランザクション アスペクト (あらゆる種類のメソッド呼び出しに適用するためにターゲット クラスのバイト コードを変更する) で織り込みます。AspectJ ウィービングでは、クラスパスに spring-aspects.jar が必要であり、 ロード時ウィービング(またはコンパイル時ウィービング) が有効になっている必要があります。(ロード時のウィービングの設定方法の詳細については、セクション6.8.4.5「スプリング構成」というタイトルのセクションを参照してください。)

おそらく、読み込み時間の織り込みを構成していません

于 2012-07-18T05:59:06.190 に答える
0

はい、分かりました。最初に私はここで答えを見つけたと思った

宣言型トランザクション (@Transactional) は、Spring の @Repository では機能しません

しかし、さらにテストした後、それはの場所ではないことがわかりました

<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> 

application-context.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"/>

application-context-web.xml の内容:

<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
于 2012-07-18T22:36:05.623 に答える