JDOに変更する
これまで、JPAを使っていました。
情報と実装が多いのはいいことなのかもしれませんが、@OneToManyなどのなくてもいいようなアノテーションを使用する必要があります。
1対多の関係は、クラスにおいて
List<Object> obj;
などのフィールドをつくったら自明のはず。
こんな冗長に思えるアノテーションを書かなくても良いAPIや実装があるはずです。
そんな思いと過去の苦い体験があったので、@OneToManyなどのアノテーションについては、時間がかかりそうなことが発生すればすぐに他の方法に変えようと思っていました。
今回、@OneToManyと単純に書くだけでは思ったように動かないことが判明して、あっさりとJDOに移行することにしました。
application-context.xml の修正
Springの設定を変更します。
↓削除部
上記部分は削除し、代わりに、
xxx
xxx
xxx
xxx
[
]
を追加します。
を参考にしました。
これによると、アクティブトランザクション(?)を使う場合は、allowCreateをfalseにしろとあります。
With such DAOs that rely on active transactions, it is recommended that you enforce active transactions through turning off TransactionAwarePersistenceManagerFactoryProxy's allowCreate flag:
この時、例としてあげられている、DAOプログラムはこんな感じ、
public Collection loadProductsByCategory(String category) {
PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
Query query = pm.newQuery(Product.class, "category = pCategory");
query.declareParameters("String pCategory");
return query.execute(category);
}
これを参考に、ごく単純に、
PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
pm.makePersistent(obj);
としてみましたが、
No JDO PersistenceManager bound to thread, and configuration does not allow creation of non-transactional one here
というエラーが出ます。
http://forum.springsource.org/showthread.php?39628-Transactions-IllegalStateException
このページをみて、allowCreate を true で行くことにしました。アクティブトランザクション(?)をやめたことになるんだと思います。
トランザクションの記述
それでも、Attempt to persist an object when no transaction is active
というエラーがでますので、DAOにトランザクションを記述しました。
PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
pm.makePersistent(obj);
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
DAOの記述は、下記からになります。
実際のDAO
慣例に従い、XxxxDAO はインタフェースに変更。クラスは XxxxDAOImpl にしました。
JDOのアノテーションがうまく使えたら、もっとすっきりするかもしれません。
public interface SiteMakingDAO {
public void persist(SiteMaking siteMaking);
}
@Componentのアノテーションはつけていません。
実装する側は、
public class SiteMakingDAOImpl implements SiteMakingDAO {
private PersistenceManagerFactory persistenceManagerFactory;
public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
this.persistenceManagerFactory = pmf;
}
public void persist(SiteMaking siteMaking){
PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
pm.makePersistent(siteMaking);
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
}
}
としました。@Component アノテーションはつけていません。Spring設定ファイルの記述によりインスタンス化されます。
モデルの修正
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class SiteMaking implements IWork,Serializable{
private static final long serialVersionUID = 1L;
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
@Persistent
private String name;
@Persistent
private List jobs;
@Persistent
private String remark;
public SiteMaking(){
}
// 以下、セッター、ゲッター
}
JPAで使用する、@Column アノテーションを残していたらエラーが出ました。
単純に消します。