技术标签: Mybatis配置文件 JavaEE Mybatis配置文件详解 深入理解Mybatis Mybatis
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标签,读取java配置文件的内容 -->
<properties resource="db.properties" />
<!-- 配置mybatis的环境信息 -->
<environments default="development">
<environment id="development">
<!-- 配置JDBC事务控制,由mybatis进行管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源,采用dbcp连接池 -->
<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"/>
<!-- 批量定义别名(推荐) -->
<!-- [name]:指定批量定义别名的类包,别名为类名(首字母大小写都可) -->
<package name="cn.itcast.mybatis.po"/>
</typeAliases>
使用相对于类路径的资源
如:<mapperresource="sqlmap/User.xml" />
使用完全限定路径
如:<mapperurl="file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml"/>
使用mapper接口的全限定名
如:<mapperclass="cn.itcast.mybatis.mapper.UserMapper"/>
注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;
注册指定包下的所有映射文件
如:<package name="cn.itcast.mybatis.mapper"/>
注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;
指定输入参数的java类型,可以使用别名或者类的全限定名。它可以接收简单类型、POJO、HashMap。
参考入门需求:根据用户ID查询用户信息。
参考入门需求:添加用户。
开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
1、需求:
综合查询用户信息,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息)。
2、定义包装类对象
一般User.java类要和数据表表字段一致,最好不要在这里面添加其他字段,第二天学习mybatis的逆向工程时,会根据表结构,生成po类,如果在po类中扩展字段,此时会被覆盖掉。
所以针对要扩展的po类,我们需要创建一个扩展类,来继承它。
定义POJO包装类:
3、编写Mapper接口
//通过包装类来进行复杂的用户信息综合查询
public List<UserExt>findUserList(UserQueryVO userQueryVO);
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<UserExt> list =userMapper.findUserList(userQueryVO);
System.out.println(list);
// 关闭SqlSession
sqlSession.close();
}
同传递POJO对象一样,map的key相当于pojo的属性。
1、映射文件
<!-- 传递hashmap综合查询用户信息 -->
<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<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获取值为空。
使用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<User>findUsersByName(String username);
总结:同样的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-->
<!--
[id]:定义resultMap的唯一标识
[type]:定义该resultMap最终映射的pojo对象
[id标签]:映射结果集的唯一标识列,如果是多个字段联合唯一,则定义多个id标签
[result标签]:映射结果集的普通列
[column]:SQL查询的列名,如果列有别名,则该处填写别名
[property]:pojo对象的属性名
-->
<resultMap type="user" id="userResultMap">
<id column="id_" property="id"/>
<result column="username_" property="username"/>
<result column="sex_" property="sex"/>
</resultMap>
定义statement:
<!-- 根据ID查询用户信息(学习resultMap) -->
<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<UserExt>findUserList(UserQueryVO userQueryVO);
//综合查询用户总数
public int findUsersCount(UserQueryVOuserQueryVO);
4、测试代码:
不传用户名:
输出的SQL如下(也不包含用户名):
通过测试可以得知,打印出的SQL语句确实会随着条件的满足情况而不一样。
Mybatis提供了SQL片段的功能,可以提高SQL的可重用性。
1、定义sql片段
使用sql标签来定义一个SQL片段:
<!-- 定义SQL片段 -->
<!--
[sql标签]:定义一个SQL片段
[id]:SQL片段的唯一标识
建议:
1、SQL片段中的内容最好是以单表来定义
2、如果是查询字段,则不要写上SELECT
3、如果是条件语句,则不要写上WHERE
-->
<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片段
使用<include refid=’’ /> 来引用SQL片段:
<!-- 根据用户id来查询用户信息(使用SQL片段) -->
<!--
[include标签]:引用已经定义好的SQL片段
[refid]:引用的SQL片段id
-->
<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、映射文件
<!-- [foreach标签]:表示一个foreach循环 -->
<!-- [collection]:集合参数的名称,如果是直接传入集合参数,则该处的参数名称只能填写[list]。 -->
<!-- [item]:每次遍历出来的对象 -->
<!-- [open]:开始遍历时拼接的串 -->
<!-- [close]:结束遍历时拼接的串 -->
<!-- [separator]:遍历出的每个对象之间需要拼接的字符 -->
<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<UserExt> findUserList(UserQueryVO vo);
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<Integer> idList = newArrayList<Integer>();
idList.add(1);
idList.add(10);
idList.add(16);
vo.setIdList(idList);
// 调用mapper代理对象的方法
List<UserExt> list =mapper.findUserList(vo);
System.out.println(list);
// 关闭SqlSession
sqlSession.close();
}
1、需求
根据用户ID的集合查询用户列表
2、Sql
SELECT * FROM user WHERE id IN (1,10,16)
3、映射文件
<!-- 根据用户ID的集合查询用户列表(学习foreach标签之直接传ID集合) -->
<!--
[foreach标签]:表示一个foreach循环
[collection]:集合参数的名称,如果是直接传入集合参数,则该处的参数名称只能填写[list]。
[item]:定义遍历集合之后的参数名称
[open]:开始遍历之前需要拼接的SQL串
[close]:结束遍历之后需要拼接的SQL串
[separator]:遍历出的每个对象之间需要拼接的字符
-->
<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<User>findUsersByIdList (List<Integer> idList);
5、测试代码
@Test
publicvoid findUsersByIdListTest() {
// 创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通过SqlSession,获取mapper接口的动态代理对象
UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
// 构造List<Integer>集合
List<Integer> idList = new ArrayList<Integer>();
idList.add(1);
idList.add(10);
idList.add(16);
// 调用mapper对象的方法
List<User> list =userMapper.findUsersByIdList (idList);
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]
文章浏览阅读451次。dev/mem: 物理内存的全镜像。可以用来访问物理内存。/dev/kmem: kernel看到的虚拟内存的全镜像。可以用来访问kernel的内容。调试嵌入式Linux内核时,可能需要查看某个内核变量的值。/dev/kmem正好提供了访问内核虚拟内存的途径。现在的内核大都默认禁用了/dev/kmem,打开的方法是在 make menuconfig中选中 device drivers --> ..._dev/mem 源码实现
文章浏览阅读7.1k次,点赞2次,收藏19次。vxe-table,一个小众但功能齐全并支持excel操作的vue表格组件_vxe-table
文章浏览阅读62次。参考:http://www.ruanyifeng.com/blog/2016/01/babel.htmlBabelBabel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行// 转码前input.map(item => item + 1);// 转码后input.map(function (item) { return item..._让开发环境支持bable
文章浏览阅读2.8k次,点赞6次,收藏29次。摘要:FPGA视频处理FIFO的典型应用,视频输入FIFO的作用,视频输出FIFO的作用,视频数据跨时钟域FIFO,视频缩放FIFO的作用_fpga 频分复用 视频
文章浏览阅读575次。【代码】R语言:设置工作路径为当前文件存储路径。_r语言设置工作目录到目标文件夹
文章浏览阅读452次。格式:background: linear-gradient(direction, color-stop1, color-stop2, ...);<linear-gradient> = linear-gradient([ [ <angle> | to <side-or-corner>] ,]? &l..._background线性渐变
文章浏览阅读1k次,点赞26次,收藏8次。第十三届蓝桥杯青少年组python编程省赛真题一、题目要求(注:input()输入函数的括号中不允许添加任何信息)1、编程实现给定一个正整数N,输出正整数N中各数位最大的那个数字。例如:N=132,则输出3。2、输入输出输入描述:只有一行,输入一个正整数N输出描述:只有一行,输出正整数N中各数位最大的那个数字输入样例:
文章浏览阅读2.2k次。一个网络协议主要由以下三个要素组成:1.语法数据与控制信息的结构或格式,包括数据的组织方式、编码方式、信号电平的表示方式等。2.语义即需要发出何种控制信息,完成何种动作,以及做出何种应答,以实现数据交换的协调和差错处理。3.时序即事件实现顺序的详细说明,以实现速率匹配和排序。不完整理解:语法表示长什么样,语义表示能干什么,时序表示排序。转载于:https://blog.51cto.com/98..._网络协议三要素csdn
文章浏览阅读153次。主要的思想,将所有的系统都可以看作两部分,真正的数据log系统和各种各样的query engine所有的一致性由log系统来保证,其他各种query engine不需要考虑一致性,安全性,只需要不停的从log系统来同步数据,如果数据丢失或crash可以从log系统replay来恢复可以看出kafka系统在linkedin中的重要地位,不光是d..._the log: what every software engineer should know about real-time data's uni
文章浏览阅读746次。伟大是熬出来的 目录 前言 引言 时间熬成伟大:领导者要像狼一样坚忍 第一章 内圣外王——领导者的心态修炼 1. 天纵英才的自信心 2. 上天揽月的企图心 3. 誓不回头的决心 4. 宠辱不惊的平常心 5. 换位思考的同理心 6. 激情四射的热心 第二章 日清日高——领导者的高效能修炼 7. 积极主动,想到做到 8. 合理掌控自己的时间和生命 9. 制定目标,马..._当狼拖着受伤的右腿逃生时,右腿会成为前进的阻碍,它会毫不犹豫撕咬断自己的腿, 以
文章浏览阅读285次。在当今的大数据时代,人们对高速度和高带宽的需求越来越大,迫切希望有一种新型产品来作为高性能计算和数据中心的主要传输媒质,所以有源光缆(AOC)在这种环境下诞生了。有源光缆究竟是什么呢?应用在哪些领域,有什么优势呢?易天将为您解答!有源光缆(Active Optical Cables,简称AOC)是两端装有光收发器件的光纤线缆,主要构成部件分为光路和电路两部分。作为一种高性能计..._aoc 光缆
文章浏览阅读2.2k次。在“桌面”上按快捷键“Ctrl+R”,调出“运行”窗口。接着,在“打开”后的输入框中输入“Gpedit.msc”。并按“确定”按钮。如下图 找到“用户配置”下的“Windows设置”下的“Internet Explorer 维护”的“连接”,双击选择“自动浏览器配置”。如下图 选择“自动启动配置”,并在下面的“自动代理URL”中填写相应的PAC文件地址。如下..._設置proxy腳本