Hibernate(JPA)拦截SQL并改写SQL

2024-08-16 17:44:06 浏览数 (1)

项目中有增加多租户的需求,原有的代码都固定了,现在进行更改的话比较麻烦,因此直接采用拦截sql并改写的方式,将对应的表增加 where tenantId = xxx。hibernate有两种拦截器:

代码语言:java复制
package org.hibernate;

import java.io.Serializable;
import java.util.Iterator;

import org.hibernate.type.Type;


public interface Interceptor {
	
	boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException;

	
	boolean onFlushDirty(
			Object entity,
			Serializable id,
			Object[] currentState,
			Object[] previousState,
			String[] propertyNames,
			Type[] types) throws CallbackException;

	
	boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException;

	
	void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException;

	
	void onCollectionRecreate(Object collection, Serializable key) throws CallbackException;

	
	void onCollectionRemove(Object collection, Serializable key) throws CallbackException;

	
	void onCollectionUpdate(Object collection, Serializable key) throws CallbackException;

	
	void preFlush(Iterator entities) throws CallbackException;

	
	void postFlush(Iterator entities) throws CallbackException;

	
	Boolean isTransient(Object entity);

	
	int[] findDirty(
			Object entity,
			Serializable id,
			Object[] currentState,
			Object[] previousState,
			String[] propertyNames,
			Type[] types);
	
	Object instantiate(String entityName, EntityMode entityMode, Serializable id) throws CallbackException;

	
	String getEntityName(Object object) throws CallbackException;

	
	Object getEntity(String entityName, Serializable id) throws CallbackException;
	
	
	void afterTransactionBegin(Transaction tx);

	
	void beforeTransactionCompletion(Transaction tx);

	
	void afterTransactionCompletion(Transaction tx);

	/**
	 * Called when sql string is being prepared. 
	 * @param sql sql to be prepared
	 * @return original or modified sql
	 *
	 * @deprecated Supply a {@link org.hibernate.resource.jdbc.spi.StatementInspector} instead, if you wish
	 * to inspect and alter SQL statements.
	 */
	@Deprecated
	String onPrepareStatement(String sql);
}

Interceptor 正常用于拦截实体类操作,我们项目很多都是手写sql,可以通过实现onPrepareStatement方法来达到我们的目的。单此方法已经标记为过期,注释里面提到了新的接口类: StatementInspector

代码语言:java复制
public interface StatementInspector extends Serializable {
	/**
	 * Inspect the given SQL, possibly returning a different SQL to be used instead.  Note that returning {@code null}
	 * is interpreted as returning the same SQL as was passed.
	 *
	 * @param sql The SQL to inspect
	 *
	 * @return The SQL to use; may be {@code null}
	 */
	public String inspect(String sql);
}

我们实现此类即可。在springboot中增加配置:

代码语言:txt复制
spring.jpa.properties.hibernate.session_factory.statement_inspector=拦截器类

即可完成拦截并改写

0 人点赞