私はクラスCreatureTypeとWeapon(あるクリーチャーに対して使用するのに最適な武器)を持っており、武器が特定のCreatureTypeに対してさまざまな効率を持っているという事実をモデル化する必要があります。そこで、効率属性を持つ関連付けエンティティCreatureTypeWeaponを作成しました。
私はそれをこのようにコーディングしました(原則は同じです)http://uaihebert.com/?p=1674&page=22
私がこの質問をしている理由は、アソシエーションエンティティにdaoクラスを実装する方法がわからないためです。
CreatureType用のDAOクラスがあり、CRUD操作でインターフェイスを実装するWeapon用のDAOクラスがあります。
しかし、私はどういうわけか、アソシエーションエンティティでのCRUD操作を処理する方法を見逃しています。私がこのDAOを持っているとしましょう
public class CreatureTypeWeaponDAOImpl implements CreatureTypeWeaponDAO {
@Override
public void create(CreatureTypeWeapon creatureTypeWeapon) {
// implementation
}
// ... other CRUD methods
}
私はそれを次のように使用します:
// this is like a person
CreatureType creatureType = new CreatureType();
creatureType.setName("alien");
creatureType.setMaxHitPoints(200);
// this is like a dog
Weapon weapon = new Weapon();
weapon.setName("ak-47");
// this is like PersonDog
CreatureTypeWeapon creatureTypeWeapon = new CreatureTypeWeapon();
creatureTypeWeapon.setWeapon(weapon);
creatureTypeWeapon.setCreatureType(creatureType);
// this is like "adoptionDate" in the link posted
// 0.5 means when I hit it with ak-47 it takes half of its max hit points
// so I have to fire 2 times on it and it will die.
creatureTypeWeapon.setEfficiency(0.5);
// this is actually injected
CreatureTypeWeaponDAO dao = new CreatureTypeWeaponDAOImpl();
dao.create(creatureTypeWeapon);
しかし、問題は、それをどのように実装するかということです。私はそれを正常に維持することができますが、この関係を削除するとしましょう:
dao.remove(creatureTypeWeapon);
これはこのように実装できます
public class CreatureTypeWeaponDAOImpl implements CreatureTypeWeaponDAO {
void remove(CreatureTypeWeapon arg) {
CreatureTypeWeapon toRemove = em.find(/* WHAT TO PUT HERE */);
em.remove(toRemove);
}
}
通常、私はそこに置きます
em.find(CreatureTypeWeapon.class, arg.getId());
しかし、関連付けエンティティに「id」はありません...。
アップデート
これが、CreatureTypeWeaponDAOImplでCreatureTypeWeaponインスタンスを取得する方法です。
TypedQuery<CreatureTypeWeapon> query =
em.createQuery(
"SELECT ctw FROM CreatureTypeWeapon ctw WHERE "
+ "creatureType = :creatureType "
+ "AND "
+ "weapon = :weapon",
CreatureTypeWeapon.class);
CreatureType creatureTypePersisted =
em.getReference(CreatureType.class, creatureType.getId());
Weapon weaponPersisted = em.getReference(Weapon.class, weapon.getId());
query.setParameter("creatureType", creatureTypePersisted);
query.setParameter("weapon", weaponPersisted);
return query.getSingleResult();
取得は問題ないようですが、removeメソッドでem.remove(creatureTypeWeapon);のように簡単に削除しようとしています。(アドバイスどおり)このエラーが発生します:
javax.persistence.NoResultException: No entity found for query at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:291)
at cz.muni.fi.pa165.creatures.dao.impl.CreatureTypeWeaponDAOImpl.get(CreatureTypeWeaponDAOImpl.java:101)
これは私がそれをテストする方法です:
public void testRemoveCreatureTypeWeapon() {
Weapon w = new Weapon("ak-47");
weaponDAO.create(w);
CreatureType ct = new CreatureType("alien", 200);
creatureTypeDAO.create(ct);
assertNotNull(weaponDAO.get(w.getId()));
assertNotNull(creatureTypeDAO.get(ct.getId()));
CreatureTypeWeapon ctw = new CreatureTypeWeapon();
ctw.setCreatureType(ct);
ctw.setWeapon(w);
ctw.setEffectivity(new Float(0.5));
creatureTypeWeaponDAO.create(ctw);
CreatureTypeWeapon ctw2 =
creatureTypeWeaponDAO.get(ctw.getCreatureType(), ctw.getWeapon());
ctw2.setCreatureType(ctw.getCreatureType());
ctw2.setWeapon(ctw.getWeapon());
creatureTypeWeaponDAO.remove(ctw);
assertNull(creatureTypeWeaponDAO.get(ctw2.getCreatureType(), ctw2.getWeapon()));
}
更新#2
わかりました。このようなエラーが発生した理由は、query.getSingleResult()がNoResultExceptionをスローしたときに、テストで削除した後にエンティティを取得しようとすると、そのようなレコードがないため、メソッドがスローするためです。実行、それは良いことです。私はそれを次のように扱いました:
try {
return query.getSingleResult();
} catch(NoResultException ex) {
return null;
}
そうすれば、正常に削除することができます(それ以前でも実行可能でしたが、混乱してエラーが発生したと思いました)。