1. 程式人生 > >Mybatis實現Mapper介面的簡單案例

Mybatis實現Mapper介面的簡單案例

用了很久mybatis,一直猜想mybatis是使用動態代理的方式實現mapper介面的,通過實踐探索之後,果然如此,但是還是遇到了不少問題,在此粘出來供初學者參考。
首先我將案例程式碼粘出來,這段程式碼簡單實現了從service層開始呼叫mapper介面的過程。

package com.star.ott.common.office;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestClass {

    public static void main(String[] args) {
        new UserService().updateUserByUserName();
        new UserService().findUser("");
    }

}
/**
 * 我們需要操作的user實體
 */
class User {
    private String userName;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}
/**
 * 這裡是我們的mapper介面
 */
interface UserMapper {
    User findUserByUserName(String userName);

    void updateUserByUserName(User user);
}

/**
 * 此處是service層的業務類
 */
class UserService {
	//在實際開發中,此處的UserMapper是通過註解載入進來的,而其真正的
	//實現就類似於下面的實現方式,通過動態帶來的方式建立例項
    UserMapper userMapper = (UserMapper) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{UserMapper.class}, new MybatisProxy());

    public User findUser(String userName) {
        return userMapper.findUserByUserName(userName);
    }

    public void updateUserByUserName() {
        userMapper.updateUserByUserName(new User());
    }
}
/**
 * 這裡就是具體的代理類,在代理類中,通過資料庫驅動與資料庫獲取
 * 連線,然後讀取相關mapper.xml執行sql,最後獲得操作結果,具體
 * 連線資料庫,讀取mapper.xml檔案的方式就不再累贅
 */
class MybatisProxy implements InvocationHandler {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("遍歷引數" + method.getParameters()[0]);
        System.out.println("通過method的名字去mapper.xml檔案中找到sql: " + method.getName());
        System.out.println("執行資料庫操作,若果有異常等,直接在此處丟擲,沒有則拿到返回值");
        if(method.getReturnType().toString().equals("void")){
            System.out.println("無返回值的情況");
            return method.getGenericReturnType();
        }else {
            Object result = method.getReturnType().getDeclaredConstructor().newInstance();
            System.out.println("將得到的返回值賦值給result,然後返回" + method.getReturnType());
            return result;
        }
    }
}



需要注意的是,通過Proxy.newProxyInstance方式生成代理物件時,一般除了需要介面類的類型別之外,還需要實現類的例項作為代理類的引數,這樣,我們就可以在代理物件中,也就是MybatisProxy中直接執行實現類例項的方法,然後返回。但是我們此處代理物件的特殊之處,就是代理了介面,實現邏輯完全寫在代理類中,所以遇到沒有返回值的方法時,需要做邏輯判斷,返回一個method.getGenericReturnType(),否則這裡會報錯。
好了,這就是mybatis通過動態代理的方式實現mapper介面的大致方式,可以參考一下。