攔截器就是直接某個動作時,攔截下來做某件事,和PL/SQL的TRIGGER類似
先不管mybatis的設定,先寫個main method,注意內部類別:
public static void main(String[] args) {
List<String> list = (List<String>) new MyInterceptor()
.plugin(new ArrayList<>());
list.add(0, "aaa");
}
@Intercepts(value = { @Signature(args = { int.class, Object.class }, method = "add", type = List.class) })
private static class MyInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("intercept");
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
System.out.println("plugin");
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
System.out.println("setProperties");
}
}
結果:
plugin
intercept
.args是小括弧的參數
.只要執行了add方法,就會攔截
.setProperties會先執行,但目前還沒寫,再來是plugin method,最後是intercept method
.如果想攔截其他方法,但沒有參數,就寫args = {}
.只要設定有錯,就會拋找不到方法的錯誤訊息
※先用Mybatis3.x(九)的例子,可以run再說
由於我Mybatis3.x(九)的程式碼不見了,只好再做一次了,這一次做不一樣的好了
CREATE TABLE DEPT (
DEPTNO NUMBER NOT NULL,
DNAME VARCHAR2(255 BYTE),
LOC VARCHAR2(255 BYTE),
CONSTRAINT DEPT_PK PRIMARY KEY(DEPTNO)
);
INSERT INTO DEPT (DEPTNO,DNAME,LOC) VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO DEPT (DEPTNO,DNAME,LOC) VALUES (20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT (DEPTNO,DNAME,LOC) VALUES (30, 'SALES', 'CHICAGO');
INSERT INTO DEPT (DEPTNO,DNAME,LOC) VALUES (40, 'OPERATIONS', 'BOSTON');
vo類,故意和資料庫取不一樣的名字
public class Department {
private Integer deptno;
private String dname;
private String loc;
//setter/getter...
}
DAO:
public interface IDepartmentDAO {
@Insert("INSERT INTO DEPT(DEPTNO, DNAME, LOC) VALUES (#{deptno}, #{dname}, #{loc})")
public boolean insert(Department vo);
@Select("SELECT DEPTNO, DNAME, LOC FROM DEPT")
public List<Department> findAll();
}
mybatis-config.xml最後要加這一段,有四種方式,可參考Mybatis3.x(九)
<mappers>
<mapper class="dao.IDepartmentDAO"/>
</mappers>
測試類:
SqlSession sqlSession = MybatisUtil.getSession();
//查詢
IDepartmentDAO dao = sqlSession.getMapper(IDepartmentDAO.class);
Iterator<Department> iter = dao.findAll().iterator();
while (iter.hasNext()) {
Department dept = iter.next();
System.out.println("getDeptno=" + dept.getDeptno());
System.out.println("getDname=" + dept.getDname());
System.out.println("getLoc=" + dept.getLoc());
System.out.println("=========================");
}
//新增
Department dept2 = new Department();
dept2.setDeptno(50);
dept2.setDname("MONEY");
dept2.setLoc("FRANCH");
IDepartmentDAO dao2 = sqlSession.getMapper(IDepartmentDAO.class);
System.out.println(dao2.insert(dept2));
sqlSession.commit();
MybatisUtil.closeSession();
都可以run後,再加攔截器的程式碼
※攔截器
有兩個地方要加
mybatis-config.xml加這一段,注意順序,錯誤會有提示
<plugins>
<plugin interceptor="plugin.MyInterceptor">
<property name="param1" value="abc" />
<property name="param2" value="123" />
</plugin>
</plugins>
繼承Interceptor的類別:
@Intercepts(value = {
@Signature(args = { MappedStatement.class, Object.class,
RowBounds.class, ResultHandler.class }, method = "query", type = Executor.class),
@Signature(args = { Connection.class }, method = "prepare", type = StatementHandler.class) })
public class MyInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object result = invocation.proceed();
System.err.println("result=" + result);
return result;
}
@Override
public Object plugin(Object target) {
System.err.println("target=" + target);
return Plugin.wrap(target, this);
}
// 取得properties,設定在mybatis-config.xml
@Override
public void setProperties(Properties properties) {
String param1 = properties.getProperty("param1");
String param2 = properties.getProperty("param2");
System.err.println("param1 = " + param1);
System.err.println("param2 = " + param2);
}
}
官方提供四種支援如下:
.org.apache.ibatis.executor.Executor
.org.apache.ibatis.executor.parameter.ParameterHandler
.org.apache.ibatis.executor.resultset.ResultSetHandler
.org.apache.ibatis.executor.statement.StatementHandler
其中StatementHandler又有兩個實作類別
BaseStatementHandler(抽象)和RoutingStatementHandler
BaseStatementHandler又有三個兒子
CallableStatementHandler:處理CallableStatement
PreparedStatementHandler:處理PreparedStatement
SimpleStatementHandler:處理Statement
.第一個Signature針對查詢,主要用
abstract <E> List<E>
query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler)
.第二個Signature有連資料庫就在呼叫方法之前攔截,所以增刪改查都OK
abstract Statement
prepare(Connection connection)
.測試時,result有印出來才表示有成功攔截
.使用這些方法時,我是理解出來的,因為官方網站的API,都沒寫註解,原始碼我也看不太懂