Hibernate 拦截器实例

本文详细解释了Hibernate拦截器如何在数据库操作中发挥作用,包括事务管理、持久化对象以及对象信息的记录。通过实现一个自定义拦截器类,展示了拦截器在事务开始、结束以及持久化后调用的方法,以及如何通过ThreadLocal存储和处理持久化对象信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hibernate 在操作数据库的时候要执行很多操作,这些动作对用户是透明的。这些操作主要是有拦截器和时间组成

 hibernate拦截器可以拦截大多数动作,比如事务开始之后(afterTransactionBegin)、事务完成之前(beginTransactionCompletion)、事务完成之后(afterTransactionCompletion)、持久化对象之前(onSave),一个拦截器必须实现org.hibernate.Interceptor借口,hibernate提供了一个实现该借口的类EmptyInterceptor类

下面编写一个hibernate实例来说明hibernate拦截器的作用

首先编写一个保存持久化对象的信息类EntityInfo

public class EntityInfo {

	public Object entityBean;
	public Serializable id;
	public String[] properties;
	public Object getEntityBean() {
		return entityBean;
	}
	public void setEntityBean(Object entityBean) {
		entityBean = entityBean;
	}
	public Serializable getId() {
		return id;
	}
	public void setId(Serializable id) {
		this.id = id;
	}
	public String[] getProperties() {
		return properties;
	}
	public void setProperties(String[] properties) {
		this.properties = properties;
	}
	public String toString()
	{
		String info = "";
		if(entityBean !=null){
			info = entityBean.getClass().toString()+"\r\nid:"+id+"\r\n";
			if(properties != null){
				//处理properties中的所有元素
				for(String property:properties){
					//得到getter方法名
					try {
						String getter = "get" + property.substring(0, 1).toUpperCase()+property.substring(1);
						//使用反射技术和gettter方法名获得Method对象
						Method method = entityBean.getClass().getMethod(getter);
						//调用gettter方法,并追加生成要返回的信息
						info = info + property + ":" +method.invoke(entityBean).toString() +"\r\n";
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
		return info;
	}
}


实现拦截器类,代码如下

public class EntityBeanInterceptor extends EmptyInterceptor {
	private ThreadLocal entityBeans = new ThreadLocal();
	
	@Override
	public void afterTransactionBegin(Transaction tx){
		entityBeans.set(new HashSet<EntityInfo>());
	}
	@Override
	public void afterTransactionCompletion(Transaction tx){
		if(tx.wasCommitted()){
			Iterator i =  ((Collection)entityBeans.get()).iterator();
			while (i.hasNext()) {
				//在提交事务之后输出试题bean的内容
				EntityInfo info = (EntityInfo) i.next();
				//调用方法数据EntityBean对象
				processEntityBean(info);
			}
		}
	}
	
	
	private void processEntityBean(EntityInfo info){
		System.out.println(info);
	}
	
	@Override
	public boolean onSave(Object entity,Serializable id, Object[] state,String[] propertyNames,Type[] types){
		EntityInfo info = new EntityInfo();
		info.entityBean = entity;
		info.properties = propertyNames;
		info.id =id;
		//在持久化对象后,将对象信息保存到当前线程的HashSet<EntityInfo>对象中
		((HashSet<EntityInfo>) entityBeans.get()).add(info);
		return false;
	}
	

}


注册拦截器类,本例中在构造Session时创建拦截器类

public class HibernateSessionFactory {
	/*其他代码省略*/
	private static ThreadLocal threadLocal = new ThreadLocal();
	 private  static Configuration configuration = new Configuration();
	    private static org.hibernate.SessionFactory sessionFactory;
	public static Session getSession(Interceptor... interceptor){
		
		Session session = (Session) threadLocal.get();
		if(session == null || !session.isOpen()){
			//如果session为空重新建立一个Session工厂
			if(sessionFactory == null){
				rebuildSessionFactory();
			}
			//如果interceptor参数值中包含拦截器对象,则安装该拦截器
			session = (sessionFactory != null)?((interceptor.length == 0)?sessionFactory.openSession():sessionFactory.openSession(interceptor[0])):null;
			//如果ThreadLocal对象中没有属于当前线程的session对象,则添加一个Session对象
			threadLocal.set(session);
		}
	}

}



测试拦截器类

public class TestInterceptor {


private void mian() {
// TODO Auto-generated method stub
Session session = HibernateSessionFactory.getSession(new EntityBeanInterceptor());
Transaction tx = session.beginTransaction();
//Customer是一个实体bean
Customer customer = new Customer();
customer.setName("hqw");
session.saveOrUpdate(customer);
tx.commit();
session.close();
}
}


这样在构造session时就注册了拦截器,应为本文在EntityInterceptor类中注册了在事务开始后、事务完成后、持久化后三个方法,所以在相应地方就会调用拦截器中的方法

### 整合 Hibernate 拦截器到 Spring Boot 的方法 在 Spring Boot 中整合 Hibernate 拦截器可以用于实现自定义逻辑或审计功能。以下是具体的方法: #### 配置 `LocalSessionFactoryBean` 或 `EntityManagerFactory` 由于 Spring Boot 自动配置了 Hibernate,因此可以通过设置 `hibernate.session_factory.interceptor` 属性来指定拦截器类。 ```properties spring.jpa.properties.hibernate.session_factory.interceptor=com.example.CustomInterceptor ``` 此属性会告诉 Hibernate 使用哪个拦截器实例[^1]。 #### 创建自定义拦截器类 创建一个继承自 `org.hibernate.EmptyInterceptor` 的类,并重写所需的方法。例如: ```java import org.hibernate.EmptyInterceptor; import java.io.Serializable; public class CustomInterceptor extends EmptyInterceptor { @Override public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { // 实现保存前的逻辑 System.out.println("Entity is being saved: " + entity); return super.onSave(entity, id, state, propertyNames, types); } @Override public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { // 实现在删除之前的逻辑 System.out.println("Entity is being deleted: " + entity); super.onDelete(entity, id, state, propertyNames, types); } } ``` 上述代码展示了如何通过覆盖 `onSave` 和 `onDelete` 方法,在实体保存和删除之前执行特定操作。 #### 注册拦截器到 Spring 应用上下文中 如果需要动态注册拦截器,则可以在应用启动时将其注入到 Bean 定义中。例如: ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AppConfig { @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, DataSource dataSource) { Map<String, Object> properties = new HashMap<>(); properties.put("hibernate.session_factory.interceptor", customInterceptor()); return builder.dataSource(dataSource).packages("com.example").persistenceUnit("unitName") .properties(properties).build(); } @Bean public CustomInterceptor customInterceptor() { return new CustomInterceptor(); } } ``` 这段代码显示了如何将拦截器作为 Bean 进行管理并传递给 `entityManagerFactory` 的配置过程[^2]。 #### 测试集成效果 完成以上步骤后,运行应用程序并通过调试验证拦截器是否按预期工作。每次触发数据库交互时,相应的拦截器方法会被调用。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值