如何在Java+Hibernate项目中实现通用CRUD操作方法
实现Hibernate通用CRUD操作的方案
嘿,我明白你想摆脱重复编写每个实体CRUD方法的烦恼,用泛型和抽象来统一处理对吧?这其实是DAO(数据访问对象)模式的典型应用,结合Hibernate的特性很容易实现。下面我一步步给你拆解:
第一步:定义通用DAO接口
先写一个通用的接口,规定所有实体都要实现的CRUD方法,用泛型来适配不同的实体和主键类型:
import java.io.Serializable; import java.util.List; public interface GenericDao<T, ID extends Serializable> { void saveOrUpdate(T entity) throws Exception; void delete(T entity) throws Exception; T findById(ID id) throws Exception; List<T> findAll() throws Exception; }
第二步:编写抽象Hibernate实现类
接下来写一个抽象类,实现上面的接口,封装Hibernate的通用操作——比如打开会话、事务管理、关闭会话这些重复代码,这样每个实体的DAO都不用再写这些了:
import org.hibernate.Session; import org.hibernate.Transaction; import java.io.Serializable; import java.util.List; public abstract class GenericHibernateDao<T, ID extends Serializable> extends Repository implements GenericDao<T, ID> { private final Class<T> entityClass; // 通过构造函数传入实体类的Class对象,Hibernate需要它来生成查询 protected GenericHibernateDao(Class<T> entityClass) { this.entityClass = entityClass; } @Override public void saveOrUpdate(T entity) throws Exception { Session session = OpenSession1(); Transaction tx = session.beginTransaction(); try { session.saveOrUpdate(entity); tx.commit(); } catch (Exception e) { tx.rollback(); throw e; } finally { CloseSession(session); } } @Override public void delete(T entity) throws Exception { Session session = OpenSession1(); Transaction tx = session.beginTransaction(); try { session.delete(entity); tx.commit(); } catch (Exception e) { tx.rollback(); throw e; } finally { CloseSession(session); } } @Override public T findById(ID id) throws Exception { Session session = OpenSession1(); T entity = session.get(entityClass, id); session.close(); return entity; } @Override public List<T> findAll() throws Exception { Session session = OpenSession1(); List<T> entities = session.createQuery("from " + entityClass.getName(), entityClass).list(); CloseSession(session); return entities; } }
这里我加了事务回滚的逻辑,避免操作失败时数据不一致,同时复用了你原Repository类里的会话管理方法,不用重复造轮子。
第三步:改造你的ManageStudent类
现在让ManageStudent继承这个抽象类,这样它自动拥有了通用的CRUD方法,你只需要保留那些特定于Student的方法(比如按studentcode查询、展示学生信息这些):
import java.sql.SQLException; import java.util.List; import org.hibernate.Session; public class ManageStudent extends GenericHibernateDao<Student, Integer> { // 构造函数传入Student的Class对象 public ManageStudent() { super(Student.class); } // 保留你原来的特定方法,比如按studentcode查询 public Student getStudent(Integer yourstcode) throws SQLException { Session session = OpenSession1(); Student student = session.createQuery("from Student s where s.studentcode=:x", Student.class) .setParameter("x", yourstcode) .uniqueResult(); session.close(); return student; } // 保留展示学生列表的方法,直接复用通用的findAll() public void showStudents() throws Exception { for (Student student : findAll()) { System.out.println("StudentID: " + student.getId()); System.out.println("Student Code: " + student.getStudentcode()); System.out.println("FirstName: " + student.getFirstName()); System.out.println("LastName:" + student.getLastName()); System.out.println("FatherName: " + student.getFatherName()); System.out.println("Age: " + student.getAge()); System.out.println("Major: " + student.getMajor()); System.out.println("------------------------------------"); } } // 保留其他特定方法 public void showStudent(Student student) { System.out.println(student.getFirstName()); System.out.println(student.getStudentcode()); System.out.println(student.getLastName()); System.out.printf("|%10s|%10s|%10s|%n", "NAME", "FAM", "AGE"); student.print(); } }
原来的addstudent、updateStudent、deletestudent、getAllStudents这些通用方法都可以删掉了,抽象类已经帮你实现了!
第四步:同理实现ManageCourse类
和ManageStudent一样,只需要继承通用抽象类,传入Course的Class对象,然后保留Course的特定方法:
import java.sql.SQLException; import java.util.Collection; import java.util.List; import org.hibernate.Session; public class ManageCourse extends GenericHibernateDao<Course, Integer> { public ManageCourse() { super(Course.class); } // 保留你的特定方法,比如按studentcode查询所选课程 public Collection<Course> getSelectedCourse(Integer yourstcode) throws SQLException { Session session = OpenSession1(); List<Course> courses = session.createQuery("from Course c join c.students s where s.studentcode=:x", Course.class) .setParameter("x", yourstcode) .list(); session.close(); return courses; } public void showCourse() throws Exception { for (Course course : findAll()) { System.out.println("Course ID: " + course.getId()); System.out.println("Course Code: " + course.getCoursecode()); System.out.println("Course Name: " + course.getCourseName()); System.out.println("------------------------------------"); } } public void showCourseSelected(Collection<Course> course3) { for (Course course : course3) { System.out.println("Course Name: " + course.getCourseName()); System.out.println("Course Code: " + course.getCoursecode()); } } }
第五步:在Run类里调用通用方法
现在你在Run类里就可以用通用方法来操作实体了,比如添加学生:
// 原来的学生对象创建逻辑不变 Student student = new Student(); student.setFirstName(stname); student.setLastName(stlname); student.setAge(stage); student.setFatherName(stfname); student.setMajor(stmajor); student.setStudentcode(yourstcode); // 现在直接用通用的saveOrUpdate方法 ManageStudent studentDao = new ManageStudent(); studentDao.saveOrUpdate(student);
删除学生的话:
// 先通过id找到学生 Student studentToDelete = studentDao.findById(stdNumber); // 调用通用delete方法 studentDao.delete(studentToDelete);
为什么这么做?
- 减少重复代码:不用给每个实体写一遍CRUD逻辑,只关注各自的特定业务方法
- 可扩展性:以后新增实体(比如Teacher),只需要继承
GenericHibernateDao,传入对应的Class对象即可 - 统一规范:所有实体的CRUD方法名都是一致的,代码更易维护
内容的提问来源于stack exchange,提问作者reihane
相关产品推荐
相关产品推荐

