mybatis-config.xml文件解释:
配置内容 | 作用 |
---|---|
<properties> | 用来加载属性文件 |
<settings> | 用来设置全局参数 |
<typeAliases> | 用来设置类型的别名 |
<typeHandlers> | 用来设置类型处理器 |
<objectFactory> | 用来设置对象工厂 |
<plugins> | 用来设置插件 |
<environments> | 用来设置mybatis的环境 |
<mappers> | 用来配置映射文件 |
1. properties加载属性文件
在实际开发中,我们需要将数据库连接参数单独配在db.properties文件中,然后在mybatis-config.xml中加载db.properties的属性值即可.
<properties resource="db.properties">
<!--对事务的管理和连接池的配置-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED"><!--POOLED:使用Mybatis自带的数据库连接池来管理数据库连接-->
<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>
在<properties>
内部还可以定义属性值:<property name="" value=""/>
,在property中定义的属性也可以被<evironments>
中来加载,这就涉及到了mybatis加载属性的顺序了:
- 在
<properties>
元素体内定义的首先被读取 - 然后读取
<properties>
元素中resource或者url加载的属性,它会覆盖已读取的同名属性 - 最后读取parameterType传递的属性(使用${}这种方式,不是#{}这种方式),它会覆盖已读的同名属性
从上面可以看出来,如果在<properties>
中定义属性的话,有点乱,搞不好就会出错,所以开发中不要在<properties>
元素体内添加任何属性值,只将属性值定义在properties文件中。另外在properties文件中定义的属性名要有一定的特殊性,如xxx.xxx,这样不容易和其他的一些属性值起冲突。
2. settings全局参数配置
mybatis框架在运行时可以调整一些运行参数,比如:开启二级缓存、开启延迟加载等,有个settings全局参数配置文档:
3. typeAliases类型别名
在mapper.xml中定义了很多的statement,statement需要parameterType来指定输入参数的类型、需要resultType来指定输出结果的类型。如果在指定类型时输入类型全路径,有时候会很长,不方便进行开发,那么我们就可以可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名<typeAliases>
来定义,方便开发。
mybatis有默认支持的一些别名,一般基本类型都有别名,如下:
但是针对pojo的需要我们自定义别名了,比如我们将自己定义的User对象取个别名为User
<typeAliases>
<!-- 其实就是将bean的替换成一个短的名字-->
<typeAlias type="com.cx.pojo.User" alias="User"/>
</typeAliases>
在使用的地方,下面的写法都是一样的。
但是问题来了,如果工程中有很多pojo,那岂不是完蛋……这得定义多少个啊,所以mybatis帮我们解决了这个问题,它提供了批量别名的定义,如下:
<!-- 批量别名定义(这个常用)
指定一个包名,mybatis会自动的扫描包中po类,自动定义别名,别名就是类名(首字母大写或小写都可以) -->
<package name="com.cx.pojo"/>
3. mappers映射配置
<!--mapping文件路径配置-->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
这里介绍另一种加载映射文件的方式:通过mapper接口来加载。通过mapper接口来加载的话要遵循一个规范:
规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中
这个规范的前提是:使用的是mapper代理的方法。
mybatis也给我们提供了批量加载方法:我们只要指定mapper接口的包名,mybatis自动扫描包下面所有的mapper接口进行加载。当然,还是要遵循上面的那个规范。
输入映射和输出映射
1. 输入映射
输入映射,是在映射文件中通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型。假设现在有个比较复杂的查询需求:完成用户信息的综合查询,需要传入查询条件很复杂(可能包括用户信息、其它信息,比如商品、订单的),那么我们单纯的传入一个User就不行了,所以首先我们得根据查询条件,自定义一个新的pojo,在这个pojo中包含所有的查询条件。
1.1 定义包装类型pojo
定义一个UserQueryVo类,将要查询的条件包装进去。这里为了简单起见,就不添加其他的查询条件了,UserQueryVo中就包含一个User,假设复杂的查询条件在User中都已经包含了。
public class UserQueryVo {
//在这里添加所需要的查询条件
//用户查询条件,这里假设一个User就已经够了
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
//可以包装其他的查询条件,比如订单、商品等
//......
}
1.2 配置UserMapper.xml映射文件
定义好了我们自己的pojo后,需要在UserMap.xml映射文件中配置查询的statement,如下:
<select id="findUserList" parameterType="com.cx.pojo.UserQueryVo" resultType="com.cx.pojo.User">
select * from user where user.age= #{user.age} and user.name like '%${user.name}%'
</select>
我们看到,输入的parameterType的值是我们自己定义的pojo,输出的是User,当然这里的User也可以换成另一个用户自定义的pojo,包含用户所需要的条件,都行,不仅仅局限为User。然后查询条件使用OGNL表达式,取出UserQueryVo中User的相应属性即可。
1.3 定义Mapper接口
public interface UserMapper {
//省去无关代码
//用户信息综合查询
public List<User> findUserList(UserQueryVo userQueryVo) throws Exception;
}
到此为止,我们就做好了自定义的pojo输入映射了,其实并不是很难,下面测试一下这个程序是否正确:
@Test
public void testFindUserList() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//创建包装对象,设置查询条件
UserQueryVo userQueryVo = new UserQueryVo();
User user = new User();
user.setAge(12);
user.setName("abc");
userQueryVo.setUser(user);
//调用userMapper的方法
List<User> list = userMapper.findUserList(userQueryVo);
System.out.println(list);
}
输出映射
我们知道,通过resultType输出映射的时候,查询出来的列名和pojo中对应的属性名要一致才可以做正确的映射,如果不一致就会映射错误。但是如果不一致呢?该如何解决这个问题呢?这就要使用resultMap来映射了。
假设现在映射文件中有个sql语句:SELECT id id_,username username_ FROM USER WHERE id=#{id},从这个sql语句中可以看出,查询出了id和username两列,但是都起了别名了,也就是说,如果我们现在用resultType去映射到User中的话,肯定会出问题,所以我们现在要定义一个resultMap来做查询结果列与User的属性之间的一个映射。
2.1 定义resultMap
首先我们要定义一个resultMap,如下:
<resultMap type="User" id="userResultMap">
<id column="id_" property="id"/>
<result column="name_" property="name"/>
</resultMap>
关于resultMap中的几个属性,简单介绍一下它们的作用:
<resultMap>
中的type属性表示 resultMap最终映射的java对象类型。上面用的是别名,如果没有定义别名,需要使用完全限定名 <resultMap>
中的id属性是对这个resultMap的唯一标识。 <resultMap>
的子标签<id>
表示查询结果集中的唯一标识,因为id是主键。 <resultMap>
的子标签<result>
表示对查询结果集中普通名映射的定义。
子标签中的column属性:表示查询出来的列名
子标签中的property属性:表示上面type指定的pojo类型中的属性名
2.2 配置UserMapper.xml映射文件
<select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
SELECT id id_,name name_ from user where id = #{id}
</select>
2.3 定义Mapper接口
public interface UserMapper {
//省去无关代码
//根据id查询用户信息,使用resultMap输出
public User findUserByIdResultMap(int id) throws Exception;
}
对resultMap的配置和接口处理完之后,我们来写一个测试程序测试一下:
@Test
public void testFindUserByIdResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findUserByIdResultMap(1);
System.out.println(user);
}