You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:35:24