SqlMapConfig.xml的配置内容和顺序如下(顺序不能乱):
Properties(属性)
Settings(全局参数设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境信息集合)
environment(单个环境信息)
transactionManager(事物)
dataSource(数据源)
mappers(映射器)
SqlMapConfig.xml文件中可以引用java属性文件中的配置信息
db.properties配置信息如下:
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8
db.username=root
db.password=root
SqlMapConfig.xml使用properties标签后,如下所示:
<properties resource="db.properties" />
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver"value="${db.driver}"/>
<property name="url"value="${db.url}"/>
<property name="username"value="${db.username}"/>
<property name="password"value="${db.password}"/>
dataSource>
environment>
environments>
使用${},可以引用已经加载的java配置文件中的信息。
注意:mybatis将按照下面的顺序加载属性:
u Properties标签体内定义的属性首先被读取
u Properties引用的属性会被读取,如果发现上面已经有同名的属性了,那后面会覆盖前面的值
u parameterType接收的值会最后被读取,如果发现上面已经有同名的属性了,那后面会覆盖前面的值
所以说,mybatis读取属性的顺序由高到低分别是:parameterType接收的属性值、properties引用的属性、properties标签内定义的属性。
mybatis全局配置参数,全局参数将会影响mybatis的运行行为。
详细参见“mybatis学习资料/mybatis-settings.xlsx”文件
别名是使用是为了在映射文件中,更方便的去指定入参和结果集的类型,不再用写很长的一段全限定名。
别名 |
映射的类型 |
_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配置信息如下:
<typeAliases>
<typeAlias type="cn.itcast.mybatis.po.User" alias="user"/>
<package name="cn.itcast.mybatis.po"/>
typeAliases>
使用相对于类路径的资源
如:
使用完全限定路径
如:
使用mapper接口的全限定名
如:
注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;
注册指定包下的所有映射文件
如:
注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;
指定输入参数的java类型,可以使用别名或者类的全限定名。它可以接收简单类型、POJO、HashMap。
参考入门需求:根据用户ID查询用户信息。
参考入门需求:添加用户。
开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
1、需求:
综合查询用户信息,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息)。
2、定义包装类对象
一般User.java类要和数据表表字段一致,最好不要在这里面添加其他字段,第二天学习mybatis的逆向工程时,会根据表结构,生成po类,如果在po类中扩展字段,此时会被覆盖掉。
所以针对要扩展的po类,我们需要创建一个扩展类,来继承它。
定义POJO包装类:
3、编写Mapper接口
//通过包装类来进行复杂的用户信息综合查询
public List
4、编写Mapper映射文件
<select id="findUserList" parameterType="userQueryVO" resultType="userExt">
SELECT* FROM USER WHERE sex=#{userExt.sex} AND username LIKE'%${userExt.username}%'
select>
5、编写测试代码
@Test
publicvoid findUserListTest() {
// 创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通过SqlSession,获取mapper接口的动态代理对象
UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
//构造userQueryVO对象
UserQueryVO userQueryVO = new UserQueryVO();
// 构造UserExt对象
UserExt userExt = new UserExt();
userExt.setSex("1");
userExt.setUsername("小明");
userQueryVO.setUserExt(userExt);
// 调用mapper对象的方法
List
System.out.println(list);
// 关闭SqlSession
sqlSession.close();
}
同传递POJO对象一样,map的key相当于pojo的属性。
1、映射文件
<select id="findUserByHashmap" parameterType="hashmap" resultType="user">
select * from user where id=#{id} and username like '%${username}%'
select>
上边红色标注的是hashmap的key。
2、测试代码
Public void testFindUserByHashmap()throws Exception{
//获取session
SqlSessionsession = sqlSessionFactory.openSession();
//获限mapper接口实例
UserMapperuserMapper = session.getMapper(UserMapper.class);
//构造查询条件Hashmap对象
HashMap
map.put("id", 1);
map.put("username", "管理员");
//传递Hashmap对象查询用户列表
List
//关闭session
session.close();
}
异常测试:
传递的map中的key和sql中解析的key不一致。
测试结果没有报错,只是通过key获取值为空。
使用resultType进行结果映射时,需要查询出的列名和映射的对象的属性名一致,才能映射成功。
如果查询的列名和对象的属性名全部不一致,那么映射的对象为空。
如果查询的列名和对象的属性名有一个一致,那么映射的对象不为空,但是只有映射正确那一个属性才有值。
如果查询的sql的列名有别名,那么这个别名就是和属性映射的列名。
1、使用方法
使用resultType进行结果映射时,查询的列名和映射的pojo属性名完全一致,该列才能映射成功。
如果查询的列名和映射的pojo属性名全部不一致,则不会创建pojo对象;
如果查询的列名和映射的pojo属性名有一个一致,就会创建pojo对象。
2、输出简单类型
当输出结果只有一列时,可以使用ResultType指定简单类型作为输出结果类型。
第一步:Mapper映射文件
<select id="findUsersCount" parameterType="UserQueryVO"
resultType="int">
SELECT count(1) FROM USER WHERE sex =#{userExt.sex} AND username LIKE'%${userExt.username}%'
select>
第二步:Mapper接口
//综合查询用户信息总数。学习:resultType输出简单类型
public int findUsersCount(UserQueryVOvo);
第三步:测试代码
@Test
publicvoidtestFindUsersCount() {
// 创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通过SqlSession,获取mapper接口的动态代理对象
UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
//构造userQueryVO对象
UserQueryVO userQueryVO = new UserQueryVO();
// 构造UserExt对象
UserExt userExt = new UserExt();
userExt.setSex("1");
userExt.setUsername("小明");
userQueryVO.setUserExt(userExt);
int count = mapper.findUsersCount(userQueryVO);
System.out.println(count); // 关闭SqlSession
sqlSession.close();
}
3、输出POJO单个对象和列表
注意:输出单个pojo对象和pojo列表(盛放pojo对象)时,mapper映射文件中的resultType的类型是一样的,mapper接口的方法返回值不同。
第一步:Mapper映射文件
<select id="findUsersByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User">
SELECT* FROM USER WHERE username LIKE '%${value}%'
select>
第二步:Mapper接口
下面看下mapper接口的不同之处
l 输出单个pojo对象
//根据用户名称来模糊查询用户信息
public User findUsersByName(String username);
l 输出pojo列表
//根据用户名称来模糊查询用户信息列表
public List
总结:同样的mapper映射文件,返回单个对象和对象列表时,mapper接口在生成动态代理的时候,会根据返回值的类型,决定调用selectOne方法还是selectList方法。
resultMap可以进行高级结果映射(一对一、一对多映射)。
1、使用方法
如果查询出来的列名和属性名不一致,通过定义一个resultMap将列名和pojo属性名之间作一个映射关系。
l 定义resultMap
l 使用resultMap作为statement的输出映射类型。
2、需求
把下面SQL的输出结果集进行映射
SELECT id id_,username username_,sex sex_FROM USER WHERE id = 1
3、Mapper映射文件
定义resultMap:
<resultMap type="user" id="userResultMap">
<id column="id_" property="id"/>
<result column="username_" property="username"/>
<result column="sex_" property="sex"/>
resultMap>
定义statement:
<select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
SELECT id id_,username username_,sex sex_ FROM USER WHERE id =#{id}
select>
4、Mapper接口定义
//根据ID查询用户信息(学习resultMap)
public User findUserByIdResultMap(int id);
定义Statement使用resultMap映射结果集时,Mapper接口定义方法的返回值类型为mapper映射文件中resultMap的type类型。
5、测试代码
@Test
publicvoid findUserByIdResultMapTest() {
// 创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通过SqlSession,获取mapper接口的动态代理对象
UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
// 调用mapper对象的方法
User user = userMapper.findUserByIdResultMap(1);
System.out.println(user);
// 关闭SqlSession
sqlSession.close();
}
通过Mybatis提供的各种动态标签实现动态拼接sql,使得mapper映射文件在编写SQL时更加灵活,方便。常用动态SQL标签有:if、where、foreach;
Ø If标签:作为判断入参来使用的,如果符合条件,则把if标签体内的SQL拼接上。
注意:用if进行判断是否为空时,不仅要判断null,也要判断空字符串‘’;
Ø Where标签:会去掉条件中的第一个and符号。
1、需求
用户信息综合查询列表和用户信息综合查询总数这两个statement的定义使用动态SQL。
2、映射文件
<select id="findUsersByQueryVO" parameterType="cn.itcast.mybatis.po.QueryUserVO"
resultType="User">
SELECT * FROM USER
<where>
<if test="userExt !=null">
<if test="userExt.sex != null and userExt.sex != ''">
AND sex = #{userExt.sex}
if>
<if test="userExt.username != null and userExt.username !=''">
AND username LIKE'%${userExt.username}%'
if>
if>
where>
select>
<select id="findUsersCount" parameterType="QueryUserVO"
resultType="int">
SELECTcount(1) FROM USER
<where>
<if test="userExt !=null">
<if test="userExt.sex != null and userExt.sex != ''">
AND sex = #{userExt.sex}
if>
<if test="userExt.username != null and userExt.username !=''">
AND username LIKE'%${userExt.username}%'
if>
if>
where>
select>
3、Mapper接口
//通过包装类来进行复杂的用户信息综合查询
public List
//综合查询用户总数
public int findUsersCount(UserQueryVOuserQueryVO);
4、测试代码:
不传用户名:
输出的SQL如下(也不包含用户名):
通过测试可以得知,打印出的SQL语句确实会随着条件的满足情况而不一样。
Mybatis提供了SQL片段的功能,可以提高SQL的可重用性。
1、定义sql片段
使用sql标签来定义一个SQL片段:
<sql id="select_user_where">
<if test="userExt != null">
<if test="userExt.sex !=null and userExt.sex != ''">
ANDsex = #{userExt.sex}
if>
<if test="userExt.username!= null and userExt.username != ''">
AND usernameLIKE '%${userExt.username}%'
if>
if>
sql>
2、引用sql片段
使用
<select id="findUserList" parameterType="userQueryVO" resultType="userExt">
SELECT * FROM USER
<where>
<include refid="select_user_where"/>
where>
select>
<select id="findUsersCount" parameterType="QueryUserVO"
resultType="int">
SELECTcount(1) FROM USER
<where>
<include refid="select_user_where"/>
where>
select>
向sql传递数组或List时,mybatis使用foreach解析数组里的参数并拼接到SQL中。
1、需求
在用户查询列表和查询总数的statement中增加多个id输入查询。
2、Sql
SELECT * FROM user WHERE id IN (1,10,16)
3、定义pojo中的List属性
4、映射文件
<if test="idList != null and idList.size > 0">
<foreach collection="idList" item="id"open="AND id IN (" close=")" separator=",">
#{id}
foreach>
if>
5、Mapper接口
//根据用户ID的集合查询用户列表(学习foreach标签之通过POJO对象传ID集合)
public List
6、测试代码
@Test
publicvoid testFindUserList() {
// 创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通过SqlSession,获取mapper接口的动态代理对象
UserMapper mapper =sqlSession.getMapper(UserMapper.class);
// 构造QueryUserVO对象
QueryUserVO vo = new QueryUserVO();
// UserExt ext = new UserExt();
// ext.setUsername("小明");
// ext.setSex("1");
// vo.setUserExt(ext);
// 创建用户ID集合,然后设置到QueryUserVO对象中
List
idList.add(1);
idList.add(10);
idList.add(16);
vo.setIdList(idList);
// 调用mapper代理对象的方法
List
System.out.println(list);
// 关闭SqlSession
sqlSession.close();
}
1、需求
根据用户ID的集合查询用户列表
2、Sql
SELECT * FROM user WHERE id IN (1,10,16)
3、映射文件
<select id="findUsersByIdList" parameterType="java.util.List"resultType="user">
SELECT * FROM USER
<where>
<if test="list[少东家1] != null and list.size > 0">
<foreach collection="list" item="id"open="AND id IN (" close=")" separator=",">
#{id}
foreach>
if>
where>
select>
4、Mapper接口
//根据用户ID的集合查询用户列表(学习foreach标签之直接传ID集合)
public List
5、测试代码
@Test
publicvoid findUsersByIdListTest() {
// 创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通过SqlSession,获取mapper接口的动态代理对象
UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
// 构造List
List
idList.add(1);
idList.add(10);
idList.add(16);
// 调用mapper对象的方法
List
System.out.println(list);
// 关闭SqlSession
sqlSession.close();
}
Mybatis技术特点:
1、通过直接编写SQL语句,可以直接对SQL进行性能的优化;
2、学习门槛低,学习成本低。只要有SQL基础,就可以学习mybatis,而且很容易上手;
3、由于直接编写SQL语句,所以灵活多变,代码维护性更好。
4、不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。
5、需要编写结果映射。
Hibernate技术特点:
1、标准的orm框架,程序员不需要编写SQL语句。
2、具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。
3、学习门槛高,需要对数据关系模型有良好的基础,而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。
4、程序员不能自主的去进行SQL性能优化。
Mybatis应用场景:
需求多变的互联网项目,例如电商项目。
Hibernate应用场景:
需求明确、业务固定的项目,例如OA项目、ERP项目等。
如果是直接传入集合参数,则该处的参数名称只能填写[list]