I have two models, Purchase and Tag.
A Purchase can have many Tags (One to Many relationship).
What is the best (Efficent/Cleanest/etc) way to return all purchases that have one or more tags? (The actual tag entities dont have to be returned).
I’m currently using a column in the purchase table to determine if it has been tagged but would like to remove it (See PurchaseDAO for it been used)
PurchaseController:
@RequestMapping(value = "purchases/tagged", method = RequestMethod.GET)
@ResponseBody
public final List<Purchase> getTagged()
{
return RestPreconditions.checkNotNull(purchaseService.getTagged());
}
@RequestMapping(value = "purchases/pending", method = RequestMethod.GET)
@ResponseBody
public final List<Purchase> getPending()
{
return RestPreconditions.checkNotNull(purchaseService.getPending());
}
PurchaseService:
@Service
public class PurchaseService implements IPurchaseService
{
@Autowired
private IPurchaseDAO purchaseDAO;
public PurchaseService()
{
}
@Transactional
public List<Purchase> getAll()
{
return purchaseDAO.findAll();
}
@Transactional
public List<Purchase> getPending()
{
return purchaseDAO.getPending();
}
@Transactional
public List<Purchase> getTagged()
{
return purchaseDAO.getTagged();
}
}
PurchaseDAO:
@Repository
public class PurchaseDAO extends AbstractJpaDAO<Purchase> implements IPurchaseDAO {
@PersistenceContext
EntityManager entityManager;
public PurchaseDAO() {
setClazz(Purchase.class);
}
public List<Purchase> getPending() {
return entityManager.createQuery("from Purchase where tagged = 0")
.getResultList();
}
public List<Purchase> getTagged() {
return entityManager.createQuery("from Purchase where tagged = 1")
.getResultList();
}
}
Both my Purchase and Tag DAOs extend the following AbstractJpaDAO:
public abstract class AbstractJpaDAO<T extends Serializable> implements
IAbstractJpaDAO<T> {
private Class<T> clazz;
@PersistenceContext
EntityManager entityManager;
public void setClazz(final Class<T> clazzToSet) {
this.clazz = clazzToSet;
}
public T findOne(final Long id) {
return entityManager.find(clazz, id);
}
public List<T> findAll() {
return entityManager.createQuery("from " + clazz.getName())
.getResultList();
}
public void save(final T entity) {
entityManager.persist(entity);
}
}
Thanks
JB Suggestion Update
After changing PurchaseDAO getTagged() to:
public List<Purchase> getTagged() {
return entityManager.createQuery("SELECT p FROM Puchase p INNER JOIN p.tags")
.getResultList();
}
I get following error:
TRACE [http-bio-8080-exec-3] o.s.w.c.s.AnnotationConfigWebApplicationContext [AbstractApplicationContext.java:322] Publishing event in Root WebApplicationContext: ServletRequestHandledEvent: url=[/PurchaseAPIServer/api/purchases/tagged]; client=[192.168.1.17]; method=[GET]; servlet=[PurchaseAPIServer]; session=[null]; user=[null]; time=[411ms]; status=[failed: org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.hql.ast.QuerySyntaxException: Puchase is not mapped [SELECT p FROM Puchase p JOIN p.tags tag]; nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.ast.QuerySyntaxException: Puchase is not mapped [SELECT p FROM Puchase p JOIN p.tags tag]]
The inner join just makes there is at least one tag for the purchase.