1、传统调用方式
public interface IUserDao {
List<User> findAll();
}
public class UserDaoImpl implements IUserDao{
@Override
public List<User> findAll() throws Exception{
String sqlConfigPath = "sqlConfig.xml";
InputStream inputStream = Resources.getResourceAsStreasm(sqlConfigPath);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sessionFactory.openSqlSession();
List<User> userList = session.selectList("com.deppon.mapper.UserMapper.findAll");
return userList;
}
}
public class TestMybatisUtil {
public static void main(String[] args) throws Exception {
IUserDao userDao = new UserDaoImpl();
List<User> allUsers = userDao.findAll();
System.out.println(allUsers);
}
}
2、通过接口直接调用
public class DefaultSqlSession implements SqlSession{
private Configuration configuration;
public DefaultSqlSession(Configuration configuration) {
this.configuration = configuration;
}
@Override
public <T> T selectOne(String statementId, Object... args) throws IllegalAccessException, IntrospectionException, InstantiationException, SQLException, InvocationTargetException, NoSuchFieldException {
List<Object> objectList = selectList(statementId, args);
if(objectList.size() == 1){
return (T) objectList.get(0);
}else{
throw new RuntimeException("没有查询到数据");
}
}
@Override
public <T> List<T> selectList(String statementId, Object... args) throws IllegalAccessException, IntrospectionException, InstantiationException, SQLException, InvocationTargetException, NoSuchFieldException {
MapperStatement mapperStatement = configuration.getMapperStatement(statementId);
Executor executor = new SimpleExecutor();
return executor.query(configuration,mapperStatement,args);
}
@Override
public <T> T getMapper(Class<?> mapperClass){
Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// proxy 代理对象的引用 Object proxyInstance
// 获取 statementId
String className = method.getDeclaringClass().getName();
String methodName = method.getName();
String statementId = className + "." + methodName;
System.out.println("statementId:" + statementId);
// 获取方法的返回值
Type genericReturnType = method.getGenericReturnType();
// 判断是否进行了 泛型类型参数化
if(genericReturnType instanceof ParameterizedType){
List<Object> objectList = selectList(statementId, args);
return objectList;
}
return null;
}
});
return (T) proxyInstance;
}
}
public class TestMyBatisUtil{
public static void main(String[] args) throws DocumentException {
String sqlConfigPath = "sqlConfig.xml";
InputStream inputStream = Resources.getResourceAsStreasm(sqlConfigPath);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sessionFactory.openSqlSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
List<User> userList = userMapper.findAll();
for(User user:userList){
System.out.println(user);
}
}
备注:接口调用实现使用的是JDK的动态代理,生成该接口的代理对象,每次调用这个接口的所有方法,都会去执行代理对象的 invoke 方法。
1、找出 statementId
2、通过 statementId 和 args 调用 DefaultSqlSession 对象的具体方法。
接口调用注意事项:
1、接口所属的全限定类名与 xml 中的 namespace 相同
2、接口的方法名与 xml 中的 id 名相同
3、接口的参数与 xml 中 parameterType 类型一致
4、接口的返回值类型与 xml 中的 resultType 类型一致