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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值