eclipse学习(第三章:ssh中的Hibernate)——13.Hibernate的拦截器
1. 前言
本文参考自https://www.w3cschool.cn/hibernate/npyd1iek.html后做的一个实践操作。
2. 拦截器的方法
里面有很多方法,介绍一部分吧
方法 | 描述 |
---|---|
findDirty() | 这个方法在当 flush() 方法在一个 Session 对象上被调用时被调用。 |
instantiate() | 这个方法在一个持续的类被实例化时被调用。 |
isUnsaved() | 这个方法在当一个对象被传到 saveOrUpdate() 方法时被调用。 |
onDelete() | 这个方法在一个对象被删除前被调用。 |
onFlushDirty() | 这个方法在当 Hibernate 探测到一个对象在一次 flush(例如,更新操作)中是脏的(例如,被修改)时被调用。 |
onLoad() | 这个方法在一个对象被初始化之前被调用。 |
onSave() | 这个方法在一个对象被保存前被调用。 |
postFlush() | 这个方法在一次 flush 已经发生并且一个对象已经在内存中被更新后被调用。 |
preFlush() | 这个方法在一次 flush 前被调用。 |
3. 拦截器的种类
拦截器有两种,一种是session范围的,一种是sessionFactory范围的。
这里 session 范围的是这样的,但是我这个5.4版本的hibernate做不到这样,里面是无参构造,放不了自定义的拦截器。不过我看很多都是这么写的就先记录一下,可能旧版本可用吧。
SessionFactory factory = new Configuration().configure().buildSessionFactory();
Session session = factory.openSession(new MyInterceptor());
sessionFactory范围 的,本文就以这个为例子了。
SessionFactory factory = new Configuration().configure().setInterceptor(new MyInterceptor()).buildSessionFactory();
Session session = factory.openSession();
4. 项目
4.1 jar包拉取
4.2 创建对应的表student_test
student_test
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for student_test
-- ----------------------------
DROP TABLE IF EXISTS `student_test`;
CREATE TABLE `student_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(40) NOT NULL,
`subject` varchar(40) NOT NULL,
`score` double(11,0) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=102 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of student_test
-- ----------------------------
INSERT INTO `student_test` VALUES ('1', '张三', '语文', '60');
INSERT INTO `student_test` VALUES ('2', '李四', '数学', '90');
INSERT INTO `student_test` VALUES ('3', '王五', '英语', '80');
INSERT INTO `student_test` VALUES ('5', 'chen', '数学', '90');
INSERT INTO `student_test` VALUES ('90', '玩家', '物理', '70');
4.3 创建StudentTest
StudentTest
package com.czx.interceptor.pojo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "student_test")
public class StudentTest {
@Id
@Column(name = "id")
private Integer id;
@Column(name = "name")
private String name;
@Column(name = "subject")
private String subject;
@Column(name = "score")
private Double socre;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public Double getSocre() {
return socre;
}
public void setSocre(Double socre) {
this.socre = socre;
}
public StudentTest(Integer id, String name, String subject, Double socre) {
super();
this.id = id;
this.name = name;
this.subject = subject;
this.socre = socre;
}
public StudentTest() {
super();
}
@Override
public String toString() {
return "StudentTest [id=" + id + ", name=" + name + ", subject=" + subject + ", socre=" + socre + "]";
}
}
4.4 自定义拦截器
创建MyInterceptor ,为了创建一个拦截器你可以直接实现 Interceptor 类或者继承 EmptyInterceptor 类。这里有些方法返回的是boolean这种类型的值,如果为true则通行,如果为false则不会通行。
package com.czx.interceptor;
import java.io.Serializable;
import java.util.Iterator;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;
import com.czx.interceptor.pojo.StudentTest;
public class MyInterceptor extends EmptyInterceptor{
//这个方法在一个对象被删除前被调用。
@Override
public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
System.out.println("调用了onDelete方法");
}
//这个方法在当 Hibernate 探测到一个对象在一次 flush(例如,更新操作)中是脏的(例如,被修改)时被调用。
@Override
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
String[] propertyNames, Type[] types) {
System.out.println("这里是onFlushDirty方法");
if(entity instanceof StudentTest) {
System.out.println("更新操作");
return true;
}
return false;
}
//这个方法在一个对象被初始化之前被调用。
@Override
public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
System.out.println("这里是onLoad方法");
return true;
}
//这个方法在一个对象被保存前被调用。
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
System.out.println("这里是onSave方法");
if(entity instanceof StudentTest) {
System.out.println("保存操作");
return true;
}
return false;
}
//这个方法在一次 flush 已经发生并且一个对象已经在内存中被更新后被调用。
@Override
public void postFlush(Iterator entities) {
System.out.println("这是postFlush方法");
}
//这个方法在一次 flush 前被调用。
@Override
public void preFlush(Iterator entities) {
System.out.println("这是preFlush方法");
}
}
4.5 创建StudentTestManagement类
StudentTestManagement,
package com.czx.interceptor;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.czx.interceptor.pojo.StudentTest;
public class StudentTestManagement {
private static SessionFactory sessionFactory;
public static void main(String[] args) {
try {
sessionFactory = new Configuration().configure().setInterceptor(new MyInterceptor()).buildSessionFactory();
}catch (Exception e) {
System.out.println("初始化sessionFactory失败");
throw new ExceptionInInitializerError(e);
}
StudentTestManagement stm = new StudentTestManagement();
// Integer aflag = stm.addStudentTest();
// System.out.println(aflag);
// Integer dflag = stm.deleteStudentTest(101);
// System.out.println(dflag);
StudentTest st = new StudentTest(90,"萌新","化学",80.5d);
Integer uflag= stm.updateStudentTest(st);
System.out.println(uflag);
// StudentTest st2 = stm.selectStudentTest();
// System.out.println(st2);
}
//增加操作
public Integer addStudentTest() {
Session session = sessionFactory.openSession();
Transaction t = null;
Integer flag = null;
try {
t = session.beginTransaction();
StudentTest st = new StudentTest(101, "老劳", "物理", 95.5);
flag = (Integer) session.save(st);
t.commit();
}catch (HibernateException he) {
if(null != t) {
t.rollback();
}
flag = null;
he.printStackTrace();
}finally {
session.close();
}
return flag;
}
//删除操作
public Integer deleteStudentTest(Integer id) {
Session session = sessionFactory.openSession();
Integer flag = null;
Transaction transaction = null;
try {
transaction = session.beginTransaction();
StudentTest st = session.get(StudentTest.class, id);
session.delete(st);
transaction.commit();
flag = 1;
}catch (HibernateException he) {
if(null != transaction) {
transaction.rollback();
}
flag = null;
he.printStackTrace();
}finally {
session.close();
}
return flag;
}
//修改操作
public Integer updateStudentTest(StudentTest st) {
Session session = sessionFactory.openSession();
Integer flag = null;
Transaction t = null;
try {
t = session.beginTransaction();
session.update(st);
t.commit();
flag = 1;
}catch (HibernateException he) {
if(null != t) {
t.rollback();
}
flag = null;
he.printStackTrace();
}finally {
session.close();
}
return flag;
}
//查找操作
public StudentTest selectStudentTest(){
Session session = sessionFactory.openSession();
StudentTest st = null;
Transaction t = null;
try {
t = session.beginTransaction();
st = session.get(StudentTest.class, 90);
t.commit();
}catch (HibernateException he) {
if(null != t) {
t.rollback();
}
st = null;
he.printStackTrace();
}finally {
session.close();
}
return st;
}
}
4.6 测试
一个个方法来进行测试。
先进行第一个增加方法测试,测试结果为:
这里会先执行onSave方法,进入里面的操作。调用t.commit方法其实是先执行preflush方法,然后执行hibernate的数据库语句,最后执行postFlush方法。最后那个数字是我自己设置要打印的。
删除方法测试。
这里我是先根据id获取到对应的删除数据在进行删除操作的。所以最上面有查找这一行,获取到对象会执行onLoad方法
执行删除操作,会先执行onDelete方法,然后调用t.commit会调用preFlush方法,然后执行hibernate的数据库语句,然后执行postFlush方法。最后那个数字是我自己设置要打印的。
修改方法测试。
这里执行t.commit方法,会先执行preFlush方法,然后执行onFlushDirty方法,在执行hibernate的数据库语句,在执行postFlush方法。最后那个数字是我自己设置要打印的。
查找方法测试
这里会先执行hibernate的数据库语句,然后执行onLoad方法,接着执行t.commit方法会先运行preFlush方法,在运行postFlush方法。最后那个是我自己设置要打印的。
5 总结
使用t.commit方法前会用到preFlush方法,之后会用到postFlush方法。删除修改增加这类操作只有在执行这一步才会执行数据库语句。
查找的话在session.xxxxx获取数据就执行了数据库语句的。
6 项目地址
其实很简单,看看就懂了,如果不懂可以来下载看看。
https://gitee.com/mrchen13427566118/ssh_hibernate_learn.git
里面的ssh_hibernate_interceptor。
打开可以看这篇的第三点https://blog.csdn.net/weixin_43987277/article/details/116936221