ユーザーエンティティがあります:
@Entity
@Table( name = "bi_user" )
@SequenceGenerator( name = "USER_SEQ_GEN", sequenceName = "USER_SEQUENCE" )
public class User
extends DataObjectAbstract<Long>
{
private static final long serialVersionUID = -7870157016168718980L;
/**
* key for this instance. Should be managed by JPA provider.
*/
@Id
@GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "USER_SEQ_GEN" )
private Long key;
/**
* Username the user will use to login. This should be an email address
*/
@Column( nullable=false, unique=true)
private String username;
// etc. other columns and getters/setters
}
ここで、DataObjectAbstractは、jpaバージョンとequals/hashcode定義を持つ単純な@MappedSuperClass
です。
私はこのような基本的なdaoクラスを持っています
public abstract class BaseDaoAbstract<T extends DataObject<K>, K extends Serializable>
implements BaseDao<T, K>
{
@PersistenceContext
private EntityManager em;
/**
* Save a new entity. If the entity has already been persisted, then merge
* should be called instead.
*
* @param entity The transient entity to be saved.
* @return The persisted transient entity.
*/
@Transactional
public T persist( T entity )
{
em.persist( entity );
return entity;
}
/**
* merge the changes in this detached object into the current persistent
* context and write through to the database. This should be called to save
* entities that already exist in the database.
*
* @param entity The entity to be merged
* @return The merged entity.
*/
@Transactional
public T merge( T entity )
{
return em.merge( entity );
}
// other methods like persist, delete, refresh, findByKey that all delegate to em.
}
Web.xmlでOpenEntityManagerInViewフィルターを次のように定義しました
<filter>
<filter-name>openEntityManagerInViewFilter</filter-name>
<filter-class>
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
</filter-class>
<init-param>
<param-name>entityManagerFactoryBeanName</param-name>
<param-value>biEmf</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>openEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
最近、eclipselink2.3.2とSpring3.1にアップグレードし、CGLIBプロキシからSpring用のaspectJを使用したLoad Time Weavingに変換しましたが、eclipselink用にLTWを構成しませんでした。
問題は、SpringApplicationListenerに存在するこのコードにあります。コメントを参照してください。
User user = userService.findByKey(userDetails.getKey());
// THIS MERGE NEVER WRITES THROUGH TO THE DATABASE.
// THIS DOESN'T WORK AS PERSIST EITHER
user = userService.merge( user.loginSuccess() );
user.loginSuccessはいくつかのフィールドを設定し、this
を返します。コードの周りにログステートメントがあり、ブレークポイントを設定してウォークスルーできるため、コードを通過していると確信しています。私のpostgresログには、マージのためにpostgresに到達するトラフィックが表示されません。
パスワードを変更したときに別の場所にいるユーザーを含め、他のものを問題なくあちこちに保存しています。このコードは以前は機能していたことがわかっています。ここで明らかに何かが間違っていますか? OpenEntityManagerInViewFilterを誤って使用していますか?エンティティが管理対象と見なされるためには、@ Transactionalメソッドを使用する必要がありますか?どんな助けでも大歓迎です。
更新 prajeeshの提案に従ってフラッシュを試しました。これがコードです
@Transactional
public T merge( T entity )
{
entity = em.merge( entity );
em.flush();
return entity;
}
com.bi.data
のクラスで。私はこれを私の春のアプリ設定ファイルに持っています
<context:component-scan base-package="com.bi.controller,com.bi.data,com.bi.web" />
私の春の構成では私は持っています
<context:load-time-weaver/>
<tx:annotation-driven mode="aspectj"/>
次のようなaop.xmlを使用します。
<aspectj>
<weaver>
<!-- only weave classes in our application-specific packages -->
<include within="com.bi..*"/>
</weaver>
</aspectj>
そして私は
javax.persistence.TransactionRequiredException:
Exception Description: No transaction is currently active
それで、何かが明らかに誤って構成されていますが、何ですか?
更新2:ロードタイムウィービングを有効にするために変更を元に戻し、フラッシュの有無にかかわらずマージが実行されるようになりましたが、LTWの問題が何であるかはまだわかりません...
em.flush()
の後にもem.merge()
を試してください。 EntityManager
は、後で更新するために変更を保持するだけの場合があります。
EntityManagerの自動コミットはfalseです。以下のような取引をご利用ください。
EntityManager em = null;
EntityTransaction t = null;
try {
em = emf.createEntityManager();
t = em.getTransaction();
t.begin();
em.merge(myTestObject);
t.commit();
} catch (Exception e) {
t.rollback();
throw new RuntimeException(e.getMessage());
}finally{
if(em != null)
em.close();
}
私はまさに問題を抱えていて、スコープを変更することで解決しました。
@PersistenceContext(type=PersistenceContextType.EXTENDED)
transaction.begin()
メソッドとtransaction.end()
メソッドはどこにありますか? RESOURCE_LOCALでは、アプリケーションではなくトランザクションを管理する必要があります。
Spring構成ファイルに次の行があるかどうかを確認します。これにより、@ Transactionalアノテーションのサポートが有効になり、mode = "proxy"、mode = "aspectj"ではないが設定されていることも確認します。