MyBatis核心配置文件中的常用标签和Mapper文件的常用标签配置

MyBatis核心配置文件(SqlMapConfig.xml)

mybatis的全局配置文件SqlMapConfig.xml,配置内容如下:

properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)

properties属性

需求:

将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值。
在SqlMapConfig.xml中就不需要对数据库连接参数硬编码。

将数据库连接参数只配置在db.properties中,原因:方便对参数进行统一管理,在集群环境时,其它xml可以引用该db.properties。

SqlMapConfig.xml可以引用java属性文件中的配置信息如下:

在src下定义db.properties文件:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=mysql

SqlMapConfig.xml引用如下:

    <properties resource="db.properties">properties>
    <environments default="development">
        <environment id="development">
        
            <transactionManager type="JDBC" />
        
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            dataSource>
        environment>
    environments>

注意: MyBatis 将按照下面的顺序来加载属性:

  • 在 properties 元素体内定义的属性首先被读取。
  • 然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。

注意:如果在properties标签里面定义的属性被${}所引用了,对#{}不管用。那么它不会读取parameterType里面的参数值。比如properties里面定义了id属性,值为40,在映射文件中引用该值,${id} 那么我从parameterType里面传值时,不管我传基本类型还是引用类型进去都不会覆盖这个${id}值。始终都会读取40。

这里写图片描述

这里写图片描述

MyBatis核心配置文件中的常用标签和Mapper文件的常用标签配置_第1张图片

我就算通过parameter传java.lang.Interger还是传自定义包装类cn.domarvel.User取id值都不管用。最终还是被删除了。

MyBatis核心配置文件中的常用标签和Mapper文件的常用标签配置_第2张图片

因此如果用${}来读取值时,注意属性不要读取错误。而用#{}就不会出现这些问题。#{}始终读取parameterType里面的值。笔者用的是MyBatis3.4.2版本。

为了防止${},所以在普遍都是用jdbc.username的jdbc作为键的前缀。起到见名知意,不出错。

建议:

不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。
在properties文件中定义属性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX

settings(配置)

mybatis全局配置参数,全局参数将会影响mybatis的运行行为。

MyBatis核心配置文件中的常用标签和Mapper文件的常用标签配置_第3张图片

下载地址

typeAliases(类型别名)

在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型、需要resultType指定输出结果的映射类型。

如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发。

mybatis支持别名:

别名 映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal

自定义别名:

在SqlMapConfig.xml(MyBatis核心配置文件中的配置)中配置:

    <typeAliases>
        
        <typeAlias type="cn.domarvel.entity.User" alias="user"/>
        
        <package name="cn.domarvel.entity"/>
    typeAliases>

typeHandlers(类型处理器)

mybatis中通过typeHandlers完成jdbc类型和java类型的转换。

通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义.

mybatis支持类型处理器:

类型处理器 Java类型 JDBC类型
BooleanTypeHandler Boolean,boolean 任何兼容的布尔值
ByteTypeHandler Byte,byte 任何兼容的数字或字节类型
ShortTypeHandler Short,short 任何兼容的数字或短整型
IntegerTypeHandler Integer,int 任何兼容的数字和整型
LongTypeHandler Long,long 任何兼容的数字或长整型
FloatTypeHandler Float,float 任何兼容的数字或单精度浮点型
DoubleTypeHandler Double,double 任何兼容的数字或双精度浮点型
BigDecimalTypeHandler BigDecimal 任何兼容的数字或十进制小数类型
StringTypeHandler String CHAR和VARCHAR类型
ClobTypeHandler String CLOB和LONGVARCHAR类型
NStringTypeHandler String NVARCHAR和NCHAR类型
NClobTypeHandler String NCLOB类型
ByteArrayTypeHandler byte[] 任何兼容的字节流类型
BlobTypeHandler byte[] BLOB和LONGVARBINARY类型
DateTypeHandler Date(java.util) TIMESTAMP类型
DateOnlyTypeHandler Date(java.util) DATE类型
TimeOnlyTypeHandler Date(java.util) TIME类型
SqlTimestampTypeHandler Timestamp(java.sql) TIMESTAMP类型
SqlDateTypeHandler Date(java.sql) DATE类型
SqlTimeTypeHandler Time(java.sql) TIME类型
ObjectTypeHandler 任意 其他或未指定类型
EnumTypeHandler Enumeration类型 VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引)。

mappers标签(映射配置)

1.通过resource加载单个映射文件

使用相对于类路径的资源:

    
    <mappers>
        
        <mapper resource="cn/domarvel/entity/User.xml">mapper>
        <mapper resource="cn/domarvel/dao/UserMapper.xml">mapper>
    mappers>

2.

使用完全限定路径

\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml" />

3.

使用mapper接口类路径

    
    <mappers>
        
        <mapper url="cn.domarvel.dao.UserMapper"/>
    mappers>

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。并且还有一个前提是:使用的是mapper代理方法

4.

自动批量加载指定包下的所有mapper接口配置文件

    
    <mappers>
        
        <package name="cn.domarvel.dao"/>
    mappers>

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。并且还有一个前提是:使用的是mapper代理方法

Mapper.xml文件的常用标签配置

parameterType(输入类型)

#{}与${}
#{}实现的是向prepareStatement中的预处理语句中设置参数值,sql语句中#{}表示一个占位符即?。

    <select id="findUserById" parameterType="int" resultType="user">
        select * from user where id = #{id}
    select>
使用占位符#{}可以有效防止sql注入,在使用时不需要关心参数值的类型,mybatis会自动进行java类型和jdbc类型的转换。#{}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}和#{}不同,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。使用${}不能防止sql注入,但是有时用${}会非常方便,如下的例子:

    <select id="selectUserByName" parameterType="string" resultType="user">
       select * from user where username like '%${value}%'
    select>
如果本例子使用#{}则传入的字符串中必须有%号,而%是人为拼接在参数中,显然有点麻烦,如果采用${}在sql中拼接为%的方式则在调用mapper接口传递参数就方便很多。
//如果使用占位符号则必须人为在传参数中加%
List list = userMapper.selectUserByName("%管理员%");
//如果使用${}原始符号则不用人为在参数中加%
Listlist = userMapper.selectUserByName("管理员");
再比如order by排序,如果将列名通过参数传入sql,根据传的列名进行排序,应该写为:
ORDER BY ${columnName}
如果使用#{}将无法实现此功能。

其实ParameterType属性可以不用写的,不写也不会报错。但是,不写时,只要知道该怎么取那还好,但是别人看你的代码时不一定知道啊。对吧!!所以,我们还是要写ParameterType这个属性的。

传递pojo对象

Mybatis使用ognl表达式解析对象字段的值,如下例子:


    <select id="findUserByUser" parameterType="user" resultType="user">
       select * from user where id=#{id} and username like '%${username}%'
    select>

测试:

Public void testFindUserByUser()throws Exception{
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获限mapper接口实例
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //构造查询条件user对象
        User user = new User();
        user.setId(1);
        user.setUsername("管理员");
        //传递user对象查询用户列表
        Listlist = userMapper.findUserByUser(user);
        //关闭session
        session.close();
    }

异常测试:

Sql中字段名输入错误后测试,username输入dusername测试结果报错:

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'dusername' in 'class cn.itcast.mybatis.po.User'
### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'dusername' in 'class cn.itcast.mybatis.po.User'

传递pojo包装对象

  • vo视图层的东西,能够一直从视图层传递到serivce层再到持久层。
  • po持久层的类,通常和数据库表进行了绑定
  • vo和po都属于pojo自定义类
  • entity表示持久层的东西和po差不多

开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。

定义包装对象

定义包装对象将查询条件(pojo)以类组合的方式包装起来。

public class QueryVo {

    private User user;

    //自定义用户扩展类
    private UserCustom userCustom;

    //同时每个变量提供getter和setter方法

mapper.xml映射文件

MyBatis核心配置文件中的常用标签和Mapper文件的常用标签配置_第4张图片

说明:mybatis底层通过ognl从pojo中获取属性值:#{user.username},user即是传入的包装对象的属性。queryVo是别名,即上边定义的包装对象类型。

传递HashMap

Sql映射文件定义如下:


    <select id="findUserByHashmap" parameterType="hashmap" resultType="user">
       select * from user where id=#{id} and username like '%${username}%'
    select>

测试:

Public void testFindUserByHashmap()throws Exception{
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获限mapper接口实例
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //构造查询条件Hashmap对象
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("id", 1);
        map.put("username", "管理员");

        //传递Hashmap对象查询用户列表
        List<User>list = userMapper.findUserByHashmap(map);
        //关闭session
        session.close();
    }

异常测试:

  • 传递的map中的key和sql中解析的key不一致。
  • 测试结果没有报错,只是通过key获取值为空。

应用场景:

sql中多个参数没有任何的关系时,采用Map集合类型。
比如SELECT sum(score) as sumScore , avg(score) as avgScore from user

resultType(输出类型)

输出简单类型

Mapper.xml文件


    <select id="findUserCount" parameterType="user" resultType="int">
       select count(1) from user
    select>

Mapper接口

public int findUserCount(User user) throws Exception;

调用:

Public void testFindUserCount() throws Exception{
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获取mapper接口实例
        UserMapper userMapper = session.getMapper(UserMapper.class);

        User user = new User();
        user.setUsername("管理员");

        int count = userMapper.findUserCount(user);

        //关闭session
        session.close();
    }

总结:

  • 输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。如果sql返回的数据有多条也是只返回第一个数据,前提是resultType为一个基本类型。(String,Integer,等未封装多条属性的都是基本类型。比如vo就能够封装多条属性,封装String,Integer等,那么它就是复杂类型。)
  • 使用session的selectOne可查询单条记录。

输出pojo对象

参考findUserById的定义:
Mapper.xml

    
    <select id="findUserById" parameterType="int" resultType="user">
        select * from user where id = #{id}
    select>

Mapper接口:

public User findUserById(int id) throws Exception;

测试:

Public void testFindUserById() throws Exception {
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获限mapper接口实例
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //通过mapper接口调用statement
        User user = userMapper.findUserById(1);
        System.out.println(user);
        //关闭session
        session.close();
    }

使用session调用selectOne查询单条记录。

输出pojo列表

参考selectUserByName的定义:
Mapper.xml


    <select id="findUserByUsername" parameterType="string" resultType="user">
       select * from user where username like '%${value}%'
    select>

Mapper接口:

public List findUserByUsername(String username) throws Exception;
测试:
Public void testFindUserByUsername()throws Exception{
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获限mapper接口实例
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //如果使用占位符号则必须人为在传参数中加%
        //List list = userMapper.selectUserByName("%管理员%");
        //如果使用${}原始符号则不用人为在参数中加%
        List list = userMapper.findUserByUsername("管理员");
        //关闭session
        session.close();
    }

使用session的selectList方法获取pojo列表。

resultType总结:

输出pojo对象和输出pojo列表在sql中定义的resultType是一样的。
返回单个pojo对象要保证sql查询出来的结果集为单条,内部使用session.selectOne方法调用,mapper接口使用pojo对象作为方法返回值。

返回pojo列表表示查询出来的结果集可能为多条,内部使用session.selectList方法,mapper接口使用List对象作为方法返回值。

输出HashMap

输出pojo对象可以改用hashmap输出类型,将输出的字段名称作为map的key,value为字段值。

resultMap

  • resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
  • 如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中,也就是resultMap标签里面定义的type属性。
  • MyBatis框架面向sql,所以对象和sql没有关系。MyBatis将查询结果转换为指定类型的对象时,需要遵循转换的规则,resultType将查询结果字段名称和指定类型的属性名称进行匹配,如果匹配成功,那么进行反射调用,如果匹配不成功,什么都不做。在极限的情况下,一个属性都没有匹配成功!!那么对象不会创建,获取为null。反而resultMap可以解决这个问题。
  • resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list,实现一对一查询和一对多查询。
  • 能够把查询出来的多表字段分类放入到vo的多对象包装类中。比如:
public class QueryVO{
    //分别放入到这两个对象的不同属性里面。
    private User user;
    private Function function;
}

步骤:

1、定义resultMap

2、使用resultMap作为statement的输出映射类型

需求:将下边的sql使用User完成映射

SELECT id id_,username username_ FROM USER WHERE id=#{value}

User类中属性名和上边查询列名不一致。

定义resultMap

MyBatis核心配置文件中的常用标签和Mapper文件的常用标签配置_第5张图片

使用resultMap作为statement的输出映射类型

MyBatis核心配置文件中的常用标签和Mapper文件的常用标签配置_第6张图片

mapper.java

这里写图片描述

测试

MyBatis核心配置文件中的常用标签和Mapper文件的常用标签配置_第7张图片

小结

使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

你可能感兴趣的:(MyBatis)