mybati的Dao代理

Posted 小马Mark

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybati的Dao代理相关的知识,希望对你有一定的参考价值。

一些类的介绍

  1. Resources: mybatis中的一个类, 负责读取主配置文件

      InputStream in = Resources.getResourceAsStream("mybatis.xml");
    
  2. SqlSessionFactoryBuilder : 创建SqlSessionFactory对象

    SqlSessionFactoryBuilder builder  = new SqlSessionFactoryBuilder();
    //创建SqlSessionFactory对象
    SqlSessionFactory factory = builder.build(in);
    
  3. SqlSessionFactory : 重量级对象, 程序创建一个对象耗时比较长,使用资源比较多。
    在整个项目中,有一个就够用了。

    SqlSessionFactory是一个接口,接口实现类: DefaultSqlSessionFactory
    
    SqlSessionFactory作用: 获取SqlSession对象。SqlSession sqlSession = factory.openSession();
    
    openSession()方法说明:
        1. openSession() :无参数的, 获取是非自动提交事务的SqlSession对象
    	2. openSession(boolean): 
    				openSession(true)  获取自动提交事务的SqlSession. 
    	            openSession(false)  非自动提交事务的SqlSession对象
    
  4. SqlSession

    SqlSession接口:定义了操作数据的方法 
    		例如:selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()
    
    SqlSession接口的实现类DefaultSqlSession
    
    使用要求:SqlSession对象不是线程安全的,需要在方法内部使用,在执行sql语句之前,使用openSession()获取SqlSession对象。
    在执行完sql语句后,需要关闭它,执行SqlSession.close(). 这样能保证他的使用是线程安全的。
    

Dao代理实现CRUD

开发规则:

  1. 在Mapper.xml中将namespace设置为UserDao.java接口的全限定名称
  2. 将Mapper.xml中statement的id和UserDao.java接口的方法名保持一致
  3. 将Mapper.xml中statement的parameterType和UserDao.java接口的方法输入参数类型保持一致
  4. 将Mapper.xml中statement的resultType和UserDao.java接口的方法输出结果类型保持一致
  5. 注意结合业务层动态代理提交事务

动态代理的使用方式:

  • 使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象

以查询为例:

 @Test
    public void test1(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();  // 使用工具类获取sqlSession对象
        // 使用getMapper(dao接口.class)动态代理来实现dao接口
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
        // 调用dao接口里的方法
        List<Account> accounts = accountDao.selectAccount();
        accounts.forEach(account -> System.out.println(account));

        sqlSession.close();
    }

参数的理解

parameterType

  • 接口中方法参数的类型, 类型的完全限定名或别名。这个属性是可选的,因为 MyBatis可以推断出具体传入语句的参数,默认值为未设置( unset)

  • 写在mapper文件中的 一个属性。 表示dao接口中方法的参数的数据类型。

  • sql语句获取参数的值使用#{}或者${}

  • (1)使用基本数据类型(包括String)为参数

    (2)使用引用数据类型为参数

    (3)使用map为参数

别名映射类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection
iteratorIterator

一个简单参数

Dao 接口中方法的参数只有一个简单类型(java 基本类型和 String),占位符 #{ 任意字符 },和方法的参数名无关。

// dao接口中一方法
int deleteAccount(int id);   
<!--mapper文件-->
<delete id="deleteAccount">
        delete from account where id = #{id};
</delete>

多参数传递

  1. 使用@Param:

    • 当Dao接口方法多个参数,需要通过名称使用参数。在方法形参前面加入@Param(“自定义参数名”),mapper文件使用#{自定义参数名}。
    // dao接口中一方法
    List<Account> selectByParam(@Param("accountId") int id,@Param("accountName") String name);
    
    <!--mapper文件-->
    <select id="selectByParam" resultType="com.maj.domain.Account">
        select id, name, money from account where id = #{accountId} or name = #{accountName}
       											 <!-- #{这里必须与方法中的自定义的相同} -->
    </select>
    
  2. 使用对象

    • 使用java对象传递参数,java的属性值就是sql需要的参数值。每一个属性就是一个参数。
    • 语法格式:#{property,javaType=java中数据类型名,jdbcType=数据类型名称}
    • 常用格式:#{property}。javaType,jdbcType的类型MyBatis可以检测出来,一般不需要设置。
    // dao接口中一方法
    int insertAccount(Account account);
    
    <!--mapper文件-->
    <insert id="insertAccount"> 
        insert into account values (#{id},#{name},#{money});
    </insert>
    

支持的 JDBC 类型:

BITFLOATCHARTIMESTAMPOTHERUNDEFINED
TINYINTREALVARCHARBINARYBLOBNVARCHAR
SMALLINTDOUBLELONGVARCHARVARBINARYCLOBNCHAR
INTEGERNUMERICDATELONGVARBINARYBOOLEANNCLOB
BIGINTDECIMALTIMENULLCURSORARRAY
  1. 按位置
    • 参数位置从0开始,引用参数语法#{arg位置},第一个参数是#{arg0},第二个是#{arg1}
    • 注意:mybatis-3.3版本和之前的版本使用#{0},#{1}方式,从mybatis3.4开始使用#{arg0}方式。
  2. 使用Map
    • Map集合可以存储多个值,使用Map向mapper文件一次传入多个参数。
    • Map集合使用String的key,Object类型的值存储参数。
    • mapper文件使用#{key}引用参数值。

#{}和${}

使用在sql语句中的符号

  1. #{}:表示占位符,可以有效防止sql注入。使用#{}设置参数无需考虑参数的类型。
    • 更安全,更迅速,通常也是首选做法,
  2. : 表 示 拼 接 符 , 无 法 防 止 s q l 注 入 。 使 用 {}:表示拼接符,无法防止sql注入。使用 sql使{}设置参数必须考虑参数的类型。
    • 主要用在替换表名,列名,不同列排序等操作。

输出结果集

resultType

执行 sql 得到 ResultSet 转换的类型,使用类型的完全限定名或别名。

注意:

  • 如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。
  • resultType 和 resultMap,不能同时使用

返回类型:

  1. 简单类型:

    // 接口方法
    int countAccount();
    
    <!-- mapper文件 -->
    <select id="countAccount" resultType="int">
            select count(*) from Account;
    </select>
    
  2. 对象类型:

    Account selectById(int id);
    
    <select id="selectById" resultType="com.maj.domain.Account">
            select id,name,money from account where id = #{id};
    </select>
    
  3. Map类型:

    sql 的查询结果作为 Map 的 key 和 value。

    推荐使用 Map<Object,Object>。

    注意: Map 作为接口返回值, sql 语句的查询结果最多只能有一条记录。 大于一条记录是错误。

    Map<Object,Object> selectReturnMap(int id);
    
    <select id="selectReturnMap" resultType="map">
    		select id,name,money from account where id = #{id};
    </select>
    

resultMap

resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。

常用在列名和 java 对象属性名不一样的情况

使用方式:

  1. 先定义 resultMap,指定列名和属性的对应关系。
  2. <select>中把 resultType 替换为 resultMap。
 List<Account> selectUseResultMap(@Param("n") String name, @Param("m") Double money);
<!--  mapper文件  -->


    <!--
        创建resultMao标签:
          id:自定义的唯一名称,用于<select>使用
          type: 期望转为的java对象的全限定名称或别名
    -->
    <resultMap id="accountMap" type="com.maj.domain.Account">
<!--    主键字段使用id标签    -->
        <id column="id" property="id"/>
<!--    非主键字段使用result标签    -->
        <result column="name" property="name" />
        <result column="money" property="money" />
    </resultMap>

    <select id="selectUseResultMap" resultMap="accountMap">
        select id,name,money from account where name = #{n} or money=#{m};
    </select>

模糊like

模糊查询的实现有两种方式:

  1. java 代码中给查询数据加上“%”

    <select id="..." resultType="com.maj.domain.Account">
            select id,name,money from account where name = #{n};   <!--这里直接传一个参数进来即可:"%何%" -->
    </select>
    
  2. 在 mapper 文件 sql 语句的

    <select id="..." resultType="com.maj.domain.Account">
        select id,name,money from account where name = "%" #{name} "%";  <!--这里直接传一个参数进来即可:"何" -->
    </select>
    

以上是关于mybati的Dao代理的主要内容,如果未能解决你的问题,请参考以下文章

Spring+SpringMVC+MyBatis深入学习及搭建——MyBatis原始Dao开发和mapper代理开发(转发同上)

Mybatis学习---MyBatis知识原始Dao开发和mapper代理开发

spring和mybatis的整合(包含原始dao的整合方式和mapper代理整合方式)

Mybatis框架三:DAO层开发Mapper动态代理开发

Java--MyBatis的Dao方式以及Dao动态代理

MyBatis学习04mapper代理方法开发dao