การใช้ Hibernate Template และ CallBack ใน Spring Framework
จากตอนที่แล้วเราจะเห็นได้ว่า Spring เข้ามาช่วยเราในแง่ของการใช้งาน O/R ได้ง่ายและสะดวกมากขึ้นวันนี้เรา
จะมาดูกันว่าใช้ Spring กับ Hibernate จะทำให้ง่ายขึ้นพียงใด
ก่อนอื่นเรามาดูกันก่อนว่าในกรณีที่เราไม่ต้องการใช้สิ่งที่ Spring เตรียมมาให้หรือเรียกว่าใช้แบบบ้านๆเราต้องทำอะไรบ้างยกตัวอย่างที่เราต้องการเพิ่มและลบอะไรบางอย่างออกจากฐานข้อมูล
...
...
public class HibernateCourseDao implements CourseDao {
private SessionFactory sessionFactory;
public HibernateCourseDao() {
Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
}
...
public void store(Course course) {
Session session = sessionFactory.openSession();
Transaction tx = session.getTransaction();
try {
tx.begin();
session.saveOrUpdate(course);
tx.commit();
} catch (RuntimeException e) {
tx.rollback();
throw e;
} finally {
session.close();
}
}
...
public void delete(Long courseId) {
Session session = sessionFactory.openSession();
Transaction tx = session.getTransaction();
try {
tx.begin();
Course course = (Course) session.get(Course.class, courseId);
session.delete(course);
tx.commit();
} catch (RuntimeException e) {
tx.rollback();
throw e;
} finally {
session.close();
}
}
...
}
จะเห็นว่าเต็มไปด้วย boilerplate code (โปรแกรมเมอร์ต้องเขียนอะไรเต็มไปหมดทั้งๆที่งานที่ทำมีนิดเดียว) เช่น openSession, getTransaction, commit และ close ดังนั้นเป็นไปได้ไหมที่เราเอาไอ้สิ่งเหล่านี้ออกไปไว้ที่อื่นไม่ต้องตกใจ Spring
ทำให้คุณได้ครับเรามีทางเลือกสองทางคือใช้ Spring Hibernate Template กับใช้ CallBack
ก่อนอื่นเรามาดูเรื่อง Spring Hibernate Template ก่อนก็ไม่ยากเราก็ใช้ HibernateTemplate ใน DAO ของเราเหลือแค่นี้เอง
...
public class HibernateCourseDao implements CourseDao {
private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
@Transactional
public void store(Course course) {
hibernateTemplate.saveOrUpdate(course);
}
@Transactional
public void delete(Long courseId) {
Course course = (Course) hibernateTemplate.get(Course.class, courseId);
hibernateTemplate.delete(course);
}
...
}
เป็นอย่างไรบ้างครับเห็นว่า boilerpalte code ลดไปหมดเลยงานในส่วนที่ไม่เกียวข้องหายไปหมด เหลือเฉพาะเนื้องานเท่านั้นอย่างไรก็ตามสิ่งที่ Template เตรียมไว้ให้เรานั้นมีจำกัดสำหรับงานพื้นๆเท่านั้นแต่ในกรณีที่เราต้องการใช้งาน Hibernate
ในเชิงลึกมากๆและ Template ไม่สามารถช่วยเราได้เราสามารถใช้อีกทางเลือกหนึ่งคือ CallBack เช่นเราต้องการใช้ Criteria เข้ามาช่วยในการดึงข้อมูลออกมาเราสามารถทำได้ดังนี้
public Collection loadCoursesByCategory(final String category) throws DataAccessException {
return this.hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session) {
Criteria criteria = session.createCriteria(Course.class);
criteria.add(Expression.eq("category", category));
criteria.setMaxResults(6);
return criteria.list();
}
};
}
เป็นอย่างไรครับความสามารถของ Spring ในเบื้องต้นคือ code สะอาดอ่านง่ายไม่หลงครับ

งงเรื่องการ callback จังเลยครับ พอจะมีแหล่งข้อมูลเพิ่มเติม แนะนำให้หน่อยได้มั้ยครับ
@ brainstorm
จริงๆตามตัวอย่าง callback ก็คือการ query ที่มันซับซ้อนขึ้นมาโดยบางครั้งการเขียนโดยใช้ template อาจจะไม่เพียงพอครับถ้าลองดูในรายะลเอียดหรือว่าแนะนำเพิ่มเติมนะครับลองดูจากตัวอย่างได้คร่าวๆ จากที่นี่ครับ
http://docs.jboss.org/hibernate/stable/core/reference/en/html/querycriteria.html