关于mybatis的配置文件,主要有两个,一个是SqlMapperConfig.xml文件一个是mapper.xml文件,分别对这两个进行深入全面学习.
在SqlMapperConfig.xml中主要有以下标签,其中环境集合environments和spring整合后废除不用.objectFactory和plugins不经常使用.
此标签主要用来引用额外的properties文件,用来解耦xml和其他特殊的配置参数,比如对于数据库的配置,可以单独创建一个db.properties文件来保存
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/shopdemo
jdbc.username=root
jdbc.password=123456
然后在配置文件中使用$符号来引用
<configuration>
<properties resource="db.properties">
<property name="" value=""/>
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>
configuration>
如果使用这种方式就要了解mybatis对外部参数引用的过程,不然如果命名一样的参数会出现覆盖现象
1. 在 properties 元素体内定义的属性首先被读取。
2. 然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。
3. 最后读取parameterType传递的属性,它会覆盖已读取的同名属性。
因此,通过parameterType传递的属性具有最高优先级,resource或 url 加载的属性次之,最低优先级的是 properties 元素体内定义的属性。
这个是mybatis运行参数的配置,运行参数将会影响mybatis的运行行为。具体可配置的如下表.
这个是配置类型别名,一般针对自己写的pojo类,因为写全部的类路径名实在是太长了,用这个定义下会省事很多.
别名 | 映射的类型 |
---|---|
_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 |
<typeAliases>
<typeAlias type="com.aust.model.User"/>
<package name="com.aust.model"/>
typeAliases>
类型处理器用于java类型和jdbc类型映射,这个一般mybatis自带的类型处理器基本上满足日常需求,不需要单独定义。具体转换可以查询相关文档
MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。默认情况下,我们不需要配置,mybatis会调用默认实现的objectFactory。
plugins 是一个可选配置。mybatis中的plugin其实就是个interceptor, 它可以拦截Executor 、ParameterHandler 、ResultSetHandler 、StatementHandler 的部分方法,处理我们自己的逻辑。Executor就是真正执行sql语句的东西, ParameterHandler 是处理我们传入参数的,还记得前面讲TypeHandler的时候提到过,mybatis默认帮我们实现了不少的typeHandler, 当我们不显示配置typeHandler的时候,mybatis会根据参数类型自动选择合适的typeHandler执行,其实就是ParameterHandler 在选择。ResultSetHandler 就是处理返回结果的。
//使用相对于类路径的资源
"sqlmap/User.xml" />
//使用完全限定路径
"file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml" />
//使用mapper接口类路径,也就是说使用mapper代理开发dao
class="cn.itcast.mybatis.mapper.UserMapper"/>
//注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
//注册指定包下的所有mapper接口,也就是说使用mapper代理开发dao
<package name="cn.itcast.mybatis.mapper"/>
//注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
输入类型可以为简单类型,pojo类,hashmap等.
mybatis会根据预设别名typeAliases来自动解析类型
//传入简单类型int
<select id="findUserById" parameterType="int" resultType="com.aust.model.User">
SELECT * FROM user WHERE id=#{id}
select>
传入hashmap的话,则#和$取出的参数都是hashmap中的key
<select id="findUser" parameterType="java.util.HashMap" resultType="com.aust.model.User">
SELECT * FROM user WHERE id=#{id} AND nickname LIKE '%${nickname}%'
select>
测试代码
//测试取出单个
@Test
public void findUserTest(){
//获取sqlsession
SqlSession session = factory.openSession();
//创建mapper代理
UserMapper mapper = session.getMapper(UserMapper.class);
//利用mapper代理查询
HashMap<String,Object> map = new HashMap<>();
map.put("id",1);
map.put("nickname","牛");
User u = mapper.findUser(map);
session.close();
System.out.println(u);
}
有问题的就是当hashmap中对应的参数不存在的话,程序并不会报错,而是查不到结果,这里可能引发一些异常
这个如果没使用typeAliases来映射的话就直接传递完整类路径,使用的话就可以传递简单名称
<select id="findUserById" parameterType="int" resultType="com.aust.model.User">
SELECT * FROM user WHERE id=#{id}
select>
和输入类型用法差不多
<select id="findUserCount" parameterType="java.lang.String" resultType="int">
SELECT COUNT(*) from user WHERE nickname LIKE '%${value}%'
select>
要注意的是输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。
使用session的selectOne可查询单条记录。
mybatis使用session调用selectOne查询单条记录。和输入方式一样的用法
mybatis使用session的selectList方法获取pojo列表。返回数据为List
输出pojo对象可以改用hashmap输出类型,将输出的字段名称作为map的key,value为字段值。
resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系,resultMap实质上还需要将查询结果映射到pojo对象中。resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
<resultMap id="userMap" type="com.aust.model.User">
<id column="id_" property="id"/>
<result column="username_" property="username"/>
resultMap>
<select id="findUserById" parameterType="int" resultMap="userMap">
SELECT id id_,username username_,password,nickname,status FROM user WHERE id=#{id}
select>
从代码可以看出,我给id和username分别起了别名id_,username_,然后返回类型为之前定义的userMap,这样的话查询结果自动会把id_映射为User类的id,username_映射为User类的username.
下一篇关联查询会介绍更多
通过mybatis提供的各种标签方法实现动态拼接sql。
<select id="findUserList" parameterType="user" resultType="user">
select * from user
where 1=1
<if test="id!=null and id!=''">
and id=#{id}
if>
<if test="username!=null and username!=''">
and username like '%${username}%'
if>
select>
where主要解决了上面单纯用if标签还要写where 1=1这样的多余条件的情况.
<select id="findUserList" parameterType="user" resultType="user">
select * from user
<where>
<if test="id!=null and id!=''">
and id=#{id}
if>
<if test="username!=null and username!=''">
and username like '%${username}%'
if>
where>
select>
foreach遍历集合和数组进行sql语句拼接,看下面例子
SELECT * FROM USERS WHERE username LIKE '%张%' AND id IN (10,89,16)
有上面这样的sql,那么用foreach假设传了数组a{10,89,16}或者集合a{10,89,16}
"a" open=" and id in(" close=")" item="id" separator="," >
#{id}
如果传递的为数组的话,里面还有有个index属性,来表示数组的下标
Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的
sql片段用sql标签包裹起来
"query_user_where">
<if test="id!=null and id!=''">
and id=#{id}
if>
<if test="username!=null and username!=''">
and username like '%${username}%'
if>
引用方式
如果引用的为其他mapper.xml的片段,则需要使用 namespace.sql片段名
项目示例:
SSM框架整合: https://github.com/nl101531/JavaWEB
自己做的一个项目: https://github.com/nl101531/AUSTOJ