package org.multibit.mbm.db.dao.hibernate; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.transform.DistinctRootEntityResultTransformer; import org.multibit.mbm.db.dao.ItemDao; import org.multibit.mbm.db.dao.ItemNotFoundException; import org.multibit.mbm.core.model.Item; import org.multibit.mbm.core.model.ItemField; import org.multibit.mbm.core.model.ItemFieldDetail; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.HibernateTemplate; import org.springframework.stereotype.Repository; import java.sql.SQLException; import java.util.List; import java.util.Map; @Repository("hibernateItemDao") public class HibernateItemDao extends BaseHibernateDao<Item> implements ItemDao { @Override public Optional<Item> getById(Long id) throws ItemNotFoundException { return getById(Item.class, id); } @Override public Optional<Item> getBySKU(String sku) { List items = hibernateTemplate.find("from Item i where i.sku = ?", sku); return first(items); } @Override public Optional<Item> getByGTIN(String gtin) { List items = hibernateTemplate.find("from Item i where i.gtin = ?", gtin); return first(items); } @SuppressWarnings("unchecked") public List<Item> getAllByPage(final int pageSize, final int pageNumber) { return (List<Item>) hibernateTemplate.executeFind(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query = session.createQuery("from Item"); query.setMaxResults(pageSize); query.setFirstResult(pageSize * pageNumber); return query.list(); } }); } /** * Initialize various collections since we are targeting the individual entity (perhaps for display) * * @param entity The entity * * @return The entity with all collections initialized */ @Override protected Item initialized(Item entity) { return entity; } @SuppressWarnings("unchecked") @Override @Deprecated public List<Item> getByExampleByPage(final int pageSize, final int pageNumber, final Item example) { Preconditions.checkNotNull(example, "example cannot be null"); return hibernateTemplate.executeFind(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { // Examine the example object to determine the query String hql = buildHql(example); // Do the work now that the HQL is created return (List<Item>) session .createQuery(hql) .setFirstResult(pageSize * pageNumber) .setMaxResults(pageSize) .setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE) .list(); } /** * @param example The example entity * @return The HQL required to locate matching entities */ private String buildHql(Item example) { Preconditions.checkNotNull(example, "example cannot be null"); // The basic starting point String hql = "select i from Item i "; if (example != null) { // Check for simple inline fields (if applicable) // Check for complex joined fields (if applicable) if (!example.getItemFieldMap().isEmpty()) { // Potential for a complex query // Require an inner join on the item field map since there is at least one entry using it hql += "inner join i.itemFieldMap ifm where "; // Currently restrict searching against primary field entries (makes code and query simpler) boolean first=true; for (Map.Entry<ItemField, ItemFieldDetail> entry: example.getItemFieldMap().entrySet()) { ItemFieldDetail itemFieldDetail = entry.getValue(); // Compare against the ItemField ordinal and apply a wildcard using a disjunction (OR) between fields if (!first) { hql += "or "; } hql += "(ifm.itemField = "+ itemFieldDetail.getItemField().ordinal(); hql += " and lower(ifm.primaryDetail.content) like lower('%"+itemFieldDetail.getPrimaryDetail().getContent()+"%')) "; first=false; } } } return hql; } }); } @Override public Item saveOrUpdate(Item item) { hibernateTemplate.saveOrUpdate(item); return item; } /** * Force an immediate in-transaction flush (normally only used in test code) */ public void flush() { hibernateTemplate.flush(); } public void setHibernateTemplate(HibernateTemplate hibernateTemplate) { this.hibernateTemplate = hibernateTemplate; } }