I have class CreatureType and Weapon (the best weapon to use against some creature) and I need to model the fact that a weapon has various efficiency against particular CreatureType. So I created the association entity CreatureTypeWeapon which has the efficiency attribute.
I coded it in this way (the principle is the same) http://uaihebert.com/?p=1674&page=22
The reason why I am asking this question is that I don’t know how to implement dao class for the association entity.
I have the DAO class for CreatureType and I have the DAO class for Weapon which implements the interfaces with CRUD operations.
But I am somehow missing a way ho to deal with CRUD operations on the association entity. Let’s say I have this DAO
public class CreatureTypeWeaponDAOImpl implements CreatureTypeWeaponDAO {
@Override
public void create(CreatureTypeWeapon creatureTypeWeapon) {
// implementation
}
// ... other CRUD methods
}
I use it like this:
// 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);
But the question is, how to implement it? I am able to persist it normally, but let’s say I am going to remove this relationship:
dao.remove(creatureTypeWeapon);
Which could be implemented like this
public class CreatureTypeWeaponDAOImpl implements CreatureTypeWeaponDAO {
void remove(CreatureTypeWeapon arg) {
CreatureTypeWeapon toRemove = em.find(/* WHAT TO PUT HERE */);
em.remove(toRemove);
}
}
Normally, I put there
em.find(CreatureTypeWeapon.class, arg.getId());
but there is not “id” in the association entity ….
UPDATE
Ok so this is the way how I am getting a CreatureTypeWeapon instances in the CreatureTypeWeaponDAOImpl
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();
Getting seems to be ok but when I am going to remove it in the remove method as simple as em.remove(creatureTypeWeapon); (as advised) I am getting this error:
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)
This is a way how I am testing it:
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()));
}
UPDATE #2
Ok I got it, the reason there was such error was that when query.getSingleResult() throws NoResultException, it means that when I try to get the entity after its removing in the test, there is no such record, so that method throws an execption, which is good. I handled it like this:
try {
return query.getSingleResult();
} catch(NoResultException ex) {
return null;
}
After doing so, it is possible to remove it normally, (it was doable even before it but I was confused and thought the error was there).
you need to define a new table that is the join of the table
CreatureTypeandWeapon. For instance:you can then define your queries as follows:
Find by creature
Find by weapon
Find by creature and weapon
Delete