【框架】[MyBatis]DAO层只写接口,不用写实现类

转载请注明出处:http://blog.csdn.net/qq_26525215

本文源自大学之旅_谙忆的博客

团队开发一个项目,由老大架了一个框架,遇到了DAO层不用写接口了,我也是用了2次才记住这个事的,因为自己一直都是习惯于写DAO层的实现类,所以,习惯性的还是写了个实现类。于是遇到错误了。

找不到那个方法。问了团队的人才知道,方法名和Mapper中配置的id名必须一样。

实现:

一、配置Spring集成MyBatis:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"...

-------------------------------------------------

<!-- 配置数据源 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
    ...
-------------------------------------------------

<!-- 产生sqlsessionfactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:mybatis-config.xml" />
</bean>  

--------------------------------------------------

要实现对数据库的操作必须要有sqlSession,而sqlSession是由sqlSessionFactory创建的。我们可以在Spring配置好bean。

<!-- 自动扫描mapper接口-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
            p:basePackage="com.xiaojuzi.chaojijuhui.**.dao"
            p:sqlSessionFactoryBeanName="sqlSessionFactory" />

这个配置就是配置映射文件的路径,这样做的好处就是不用再写Dao的实现类了,也就是说,我们写好接口,写好配置文件,会自动映射到对应的方法和sql语句。

二、开发mapper.xml映射文件

<mapper namespace="com.xiaojuzi.chaojijuhui.user.dao.UserDao">

-------------------------------------------------------

在这里只有一个UserDao(被代理的接口)。
user.mapper.xml–namespace配置的就是UserDao的包全名。

三、开发mapper.java的接口

     /**
     * 根据用户的用户名查询用户
     * @param user
     * @return
     */
    User queryUserByLoginName (String loginName);

    /**
     * 用户通过手机号码去修改密码
     * @param userModel
     * @return
     */
    Boolean updatePasswordByMobile(UserModel userModel);

如果需要特定类型的参数,就自己再造一个POJO类(例如:UserModel)。

 <sql id="userColumns">
        u.id,
        u.login_name as "loginName",
        u.head_img as "headImg",
        ...
---------------------------------------------

<select id="queryUserByLoginName" resultType="User" parameterType="User">
        SELECT <include refid="userColumns" />
        FROM juhui_user u
        WHERE u.login_name = #{loginName}
        and u.del_flag = #{DEL_FLAG_NORMAL}
    </select>

<update id="updatePasswordByMobile" parameterType="UserModel">
        update juhui_user set
            update_date=DATE_FORMAT(#{updateDate}, '%Y-%m-%d %H:%i:%S'),
            salt = #{salt},
            password = #{password}
        where mobile = #{mobile}
    </update>

这里mapper.xml的(select、insert、update..)标签的id必须和DAO接口的方法名一样!

Mapper开发规则

1、 在mapper.xml中将namespace设置为mapper.java的全限定名
2、 将mapper.java接口的方法名和mapper.xml中statement的id保持一致。
3、 将mapper.java接口的方法输入参数类型和mapper.xml中statement的parameterType保持一致
4、 将mapper.java接口的方法输出 结果类型和mapper.xml中statement的resultType保持一致

注意遵循上边四点规范!

这样抛弃Dao实现类的写法:
具有更好的可扩展性,提高了灵活度。

原理

再根据网上的一些知识点,讲一下原理:

mybatis通过JDK的动态代理方式,在启动加载配置文件时,根据配置mapper的xml去生成Dao的实现。

session.getMapper()使用了代理,当调用一次此方法,都会产生一个代理class的instance,看看这个代理class的实现.

public class MapperProxy implements InvocationHandler {
...
public static <T> T newMapperProxy(Class<T> mapperInterface, SqlSession sqlSession) {
    ClassLoader classLoader = mapperInterface.getClassLoader();
    Class<?>[] interfaces = new Class[]{mapperInterface};
    MapperProxy proxy = new MapperProxy(sqlSession);
    return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
  } 

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (!OBJECT_METHODS.contains(method.getName())) {
      final Class<?> declaringInterface = findDeclaringInterface(proxy, method);
      final MapperMethod mapperMethod = new MapperMethod(declaringInterface, method, sqlSession);
      final Object result = mapperMethod.execute(args);
      if (result == null && method.getReturnType().isPrimitive()) {
        throw new BindingException("Mapper method '" + method.getName() + "' (" + method.getDeclaringClass() + ") attempted to return null from a method with a primitive return type (" +    method.getReturnType() + ").");
      }
      return result;
    }
    return null;
  } 

这里是用到了JDK的代理Proxy。 newMapperProxy()可以取得实现interfaces 的class的代理类的实例。

当执行interfaces中的方法的时候,会自动执行invoke()方法,其中public Object invoke(Object proxy, Method method, Object[] args)中 method参数就代表你要执行的方法.

MapperMethod类会使用method方法的methodName 和declaringInterface去取 sqlMapxml 取得对应的sql,也就是拿declaringInterface的类全名加上 sql-id..

总结:
这个就是利用JDK的代理类实现的。

本文章由[谙忆]编写, 所有权利保留。

转载请注明出处:http://blog.csdn.net/qq_26525215

本文源自大学之旅_谙忆的博客

时间: 2024-10-22 03:43:55

【框架】[MyBatis]DAO层只写接口,不用写实现类的相关文章

mybatis dao层空指针异常。

问题描述 mybatis dao层空指针异常. 严重: Servlet.service() for servlet [springmvc] in context with path [/fourth] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause java.lang.NullPointerException at com

MyBatis持久层框架的用法知识小结_java

MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录. MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google c

ssh框架的。。购物车用数据库dao层,service层,和action层怎么写啊

问题描述 ssh框架的..购物车用数据库dao层,service层,和action层怎么写啊 求大神给指点一下!!!!!!!!!!!!!!!!!!谢谢了!!!!!!!!!!!!!!!!!! 解决方案 dao层和service层Android中的分层----service 层domain层,dao 层,action层等设计Action层 Service层 ,modle层 和 Dao层的作用? 解决方案二: Action层 Service层 ,modle层 和 Dao层的作用?Action层 Ser

MyBatis持久层框架使用总结

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis . 2013年11月迁移到Github,MyBatis的Github地址:https://github.com/mybatis/mybatis-3.      iBATIS一词来源于"internet"和"abatis"的组合,是一个基于Java的持久层框架.iBAT

Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析_Android

        在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的源代码.细心的读者会发现,这几篇文章分析的Binder接口都是基于C/C++语言来实现的,但是我们在编写应用程序都是基于Java语言的,那么,我们如何使用Java语言来使用系统的Binder机制来进行进程间通信呢?这就是本文要介绍的Android系统应用程序框架层的用Java语言来实现的Binder接口了.        熟悉Android系统

如何写出一个完全和Service层剥离的dao层?

问题描述 如何写出一个完全和Service层剥离的dao层?不要在service层构造hql语句,完全只是传参数,dao层构造hql,如果换了别的持久化框架,那么只需要修改dao层就可以,service完全可以不动,这样体现出来低耦合的软件开发原则 解决方案 在Service层传来参数,使用Map传过来,然后在到层增加一个函数,专门负责在dao层生成hql语句,一般的函数都封装好了,基本要构造hql语句的,都是需要查询的,需要构造key=value形式的,所以map刚好符合,我在dao层就是这么

工具类中调用dao层的方法,spring配置如何写

问题描述 工具类中调用dao层的方法,spring配置如何写 private Set readSensitiveWord() { Set set = new HashSet(); List list = sensitiveDao.findSensitive(); if(list.size()>0){ for(Sensitive s : list){ set.add(s); } } return set; } 在这个方法中我要调用dao层的方法findSensitive().sensitiveDa

dao-jpa DAO层类如何实现继承方法或实现接口?

问题描述 jpa DAO层类如何实现继承方法或实现接口? 如果我的接口是这样定义public interface UserModelDao extends PagingAndSortingRepository, JpaSpecificationExecutor{} ,那么如果我想添加实现类来拓展方法等的话,会出现有很多继承接口中未实现的方法,如何处理这种情况?或者有什么办法来处理dao层让我能够添加新的方法或使用jpa本身的方法,使得开发灵活简单? 解决方案 AAA hibernate实现增删改

框架-axis2配置webservice,访问url能debug到service,但dao层为null

问题描述 axis2配置webservice,访问url能debug到service,但dao层为null 有人遇到过这种问题吗?如何解决?我的sturts2+spring3+mbatis框架可以跑通,但是用webservice访问不到dao层,debug进来为空.注释注入的方法不灵,写xml注入也没通过,求教高手啊,在线等