Mybatis-基本学习(下)
四,MAP的使用--超常用
思考:如何简化parameterType?总不能每次加个
@Param对应值把?
使用场景?
类似加了一层封装
- 实体类,或者数据库中的表,字段或者参数过多,就考虑使用Map
- 非常灵活,不用死死的在方法中定一个值,然后最后处理一个值的锁定。。。它可以随意定义几个值的锁定(前提是sql语句有对应)
HashMap<> 因为要调用hashcode()方法和equals()方法,进行比较,,,所以不能为基本类型
规范? -满足pojo的类型,SQL值的需求- Map需要<XX,Object>,因为Object通配所有,毕竟有Integer Double String……
使用时要---parameterType="map"使用的依据:
- 本质上parameterType就是一个送参数的,不管你送啥,你要将下面的值和sql以后要使用的参数对应就好
- 最后送参时还是要对应原本的类型的,只是使用容器作为一个中介
考虑,能否使用ArrayList---答:能 比较麻烦,没有map直接--未考虑好
注意:因为map只是送值的,所以只有put操作。。
- value分不分类型? 插入时不分,锁定值时区分 ---(最好对应-)map.put("id",8);
操作
- 1.接口中
// map的使用---万能的Map
int addUser1(Map<String,Object> map);
User getUserById1(Map<String,Object> map); // map 用法
- 2.Mapper.xml中
<!--map的使用-->
<insert id="addUser1" parameterType="map">
insert into mybatis.user(id,name,password) values (#{userId},#{userName},#{userPassword});
</insert>
<select id="getUserById1" parameterType="map" resultType="com.zjz.pojo.User">
select * from mybatis.user where id = ${id}
</select>
- 3.Test
@Test
public void TestAddUser1(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("userId",5); // 对应#{userId}--类型限制POJO
map.put("userName","zjz5"); // 对应#{userName}--类型限制POJO
map.put("userPassword","321616"); // 对应#{UserPassword}--类型限制POJO
mapper.addUser1(map);
// 提交事务
sqlSession.commit();
sqlSession.close();
}
@Test
public void TestGetUserById1(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("id","8");
User userById1 = mapper.getUserById1(map);
System.out.println(userById1);
sqlSession.close();
}
使用详情及规范
- 类型限制(POJO),值对应(SQL)
- 方法只使用 put 送值-,
- value类型没对应好,。value分不分类型? 插入时不分,锁定值时区分 ---(最好对应-)map.put("id",8);
- key没对应好,如果送的值多了,报错---少了,送null --(主键不送---肯定报错啊!)
- 注:查询时必须都得对应上key
不懂的---两个例子,你自己做一个,三列即可确定一件事了

- 备注:HashMap<> 因为要调用hashcode()方法和equals()方法,进行比较,,,所以不能为基本类型
问题以及双锁定条件
根据 密码 和 名字 查询用户
思路一:直接在方法中传递参数
- 在接口方法的参数前加 @Param属性
- ------为啥需要@Param,不加时,直接报错,因为类型影响后面
- Sql语句编写的时候,直接取@Param中设置的值即可,不需要单独设置参数类型(parameterType)
//通过密码和名字查询用户
User selectUserByNP(@Param("username") String username,@Param("pwd") String pwd); /* <select id="selectUserByNP" resultType="com.kuang.pojo.User">
select * from user where name = #{username} and pwd = #{pwd}
</select> */思路二:使用万能的Map
- 在接口方法中,参数直接传递Map;
- 编写sql语句的时候,需要传递参数类型,参数类型为map
- 在使用方法的时候,Map的 key 为 sql中取的值即可,没有顺序要求!
User selectUserByNP2(Map<String,Object> map); <select id="selectUserByNP2" parameterType="map" resultType="com.kuang.pojo.User">
select * from user where name = #{username} and pwd = #{pwd}
</select> Map<String, Object> map = new HashMap<String, Object>();
map.put("username","小明");
map.put("pwd","123456");
User user = mapper.selectUserByNP2(map);
总结:
- 如果参数过多,我们可以考虑直接使用Map实现,如果参数比较少,直接传递参数即可
@Param注解
1.使用@Param
实例一 @Param注解单一属性
// 依据id,name查询
User getUserByIdName(@Param("id") int id,@Param("name") String name);
-------------------------------------
<select id="getUserByIdName" resultType="com.zjz.pojo.User">
select * from mybatis.user where id = #{id} AND name = #{name}
</select>
1.当你使用了使用@Param注解来声明参数时,如果使用 #{} 或 ${} 的方式都可以。
// 根据id查询
User getUserById(@Param("id")int id);
<select id="getUserById" parameterType="int" resultType="com.zjz.pojo.User">
select * from mybatis.user where id = ${id}
</select>
- 2.当你不使用@Param注解来声明参数时,必须使用 #{}方式且只有一个参数。在我的版本(M361,S802) ${} 的方式,不会报错。(可能其它版本报错)
- 所以目前还是单个参数可以不用,多个参数要用
// 根据id查询
User getUserById(int id);
<select id="getUserById" parameterType="int" resultType="com.zjz.pojo.User">
select * from mybatis.user where id = ${id}
</select>
2,不使用@Param注解
- 不使用@Param注解时,参数只能有一个,可以是属性,也可以是对象
- 目前似乎不支持@param("User")
- 目前也没有此限制--
并且是Javabean。在SQL语句里可以引用JavaBean的属性,而且只能引用JavaBean的属性。
- 目前也没有此限制--
// 插入insert
int addUser(User user); <insert id="addUser" parameterType="com.zjz.pojo.User">
insert into mybatis.user(id,name,password) values (#{id},#{name},#{password});
</insert> @Test
public void TestAddUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.addUser(new User(4, "zjz4", "123456"));
// 提交事务
sqlSession.commit();
sqlSession.close(); } - 目前似乎不支持@param("User")
小结:
- 所有的增删改操作都需要提交事务!
- 接口所有的普通参数,尽量都写上@Param参数,尤其是多个参数时,必须写上!(否则报错)
- 有时候根据业务的需求,可以考虑使用map传递参数!
- 为了规范操作,在SQL的配置文件中,我们尽量将Parameter参数和resultType都写上!
五.配置解析
1.核心配置文件
- mybatis-config.xml
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
<!-- 注意元素节点的顺序!顺序不对会报错 -->
2.environments元素
配置MyBatis的多套运行环境,将SQL映射到多个不同的数据库上,必须指定其中一个为默认运行环境(通过default指定)
默认 事务JDBC 数据源 POOLED
1.子元素节点:environment
- 具体的一套环境,通过设置id进行区别,id保证唯一!
- 子元素节点:transactionManager - [ 事务管理器 ]
- ` ` 有**两个事务管理器**,不是一个!!
2.子元素节点:数据源(dataSource)
- dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
- 数据源是必须配置的。
- 有三种内建的数据源类型
type="[UNPOOLED|POOLED|JNDI]")---JNDI 正常连接- (池:用完可以回收,不关,等下一个来连)
3.属性(properties)
使用它实现引用配置文件
优先走外部的,再走里面的property
<!--引入外部配置文件-->
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>
4.别名(typeAliases)
1.起别名typeAlias
<!--起别名-->
<typeAliases>
<typeAlias type="com.zjz.pojo.User" alias="User"/>
</typeAliases> // 这样在XXXMapper.xml中的resultType就可以直接使用User,不用com.zjz.pojo.User <select id="getUserList" resultType="User" >
select * from user
</select>2.package(重要)
扫描包下的实体类,将类名首字母小写作为别名-----
可以自定义DIY --- 注解
@Alias
<!--起别名-->
<typeAliases>
<package name="com.zjz.pojo"/>
</typeAliases>
非必须:javabean 注解
@Alias("xiaoming")
- 两个之间的区别
- Aliases 可以之间手动DIY一个别名
- package 需要找到对应的javaBean,注解 ,然后就DIY的,否则都是类名首字母小写
设置
setting
一个配置完整的 settings 元素的示例如下:
<settings>
<setting name="cacheEnabled" value="true"/> <!--开关映射器配置文件中已配置的任何缓存-->
<setting name="lazyLoadingEnabled" value="true"/> <!--延迟加载的全局开关。-->
<setting name="multipleResultSetsEnabled" value="true"/> <!--是否允许单个语句返回多结果集(需要数据库驱动支持)-->
<setting name="useColumnLabel" value="true"/> <!--使用列标签代替列名-->
<setting name="useGeneratedKeys" value="false"/> <!--允许 JDBC 支持自动生成主键,需要数据库驱动支持-->
<setting name="autoMappingBehavior" value="PARTIAL"/> <!--允许 JDBC 支持自动生成主键,需要数据库驱动支持-->
<!--NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)-->
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/> <!--指定发现自动映射目标未知列(或未知属性类型)的行为。-->
<!-- NONE: 不做任何反应
WARNING: WARNING 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARN)
FAILING: FAILING 映射失败 (抛出 SqlSessionException) -->
<setting name="defaultExecutorType" value="SIMPLE"/> <!--配置默认的执行器。SIMPLE 就是普通的执行器;-->
<setting name="defaultStatementTimeout" value="25"/> <!--设置超时时间-->
<setting name="defaultFetchSize" value="100"/> <!--为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。-->
<setting name="safeRowBoundsEnabled" value="false"/> <!--禁止在嵌套语句中使用结果处理器(ResultHandler) true开启禁止-->
<setting name="mapUnderscoreToCamelCase" value="false"/> <!--是否开启驼峰命名自动映射,
即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。注:ORACLE数据库常见-->
<setting name="localCacheScope" value="SESSION"/> <!--MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。-->
<setting name="jdbcTypeForNull" value="OTHER"/> <!--当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型-->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> <!--指定对象的哪些方法触发一次延迟加载-->
</settings>其它配置
类型处理器 typeHandlers
对象工厂 objectFactory
plugins 插件
- mybatis-generator-core
- mybatis-plus-----以后学
- 通用mapper
映射(mapper)
- MapperRegistry:注册绑定我们的配置文件
- 方式一 resource(推荐使用)
<!--每一个mapper.xml都需要在mybatis核心配置文件中注册-->
<mappers>
<mapper resource="com/zjz/dao/UserMapper.xml"/>
</mappers>
- 方式二 使用class文件绑定注册
<!--每一个mapper.xml都需要在mybatis核心配置文件中注册-->
<mappers>
<mapper class="com.zjz.dao.UserMapper"/>
</mappers>
- class使用注意:
- 接口必须和他的Mapper配置文件必须同名
- 接口和他的配置文件必须在同一个包下
<environments default="test"> <!--使用test环境-->
<environment id="development">
<!-- 事务管理-->
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis? useSSL=true&useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
<environment id="test">
<!-- 事务管理-->
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis? useSSL=true&useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
生命周期和作用域
- 作用域(Scope)和生命周期
- 理解我们目前已经讨论过的不同作用域和生命周期类是至关重要的,因为错误的使用会导致非常严重的并发问题。

SqlSessionFactoryBuilder:
- 一旦创建了SqlSessionFactor,就不再需要了
- 局部变量
SqlSessionFactory:
- 生命周期就同于 MyBatis 的应用周期。
- 可以想象为:数据库连接池
- 一旦创建了 SqlSessionFactory,就要长期保存它,直至不再使用MyBatis 应用
- 往往希望 SqlSessionFactory 作为一个单例,让它在应用中被共享。所以说 SqlSessionFactory 的最佳作用域是应用作用域。
SqlSession
- 连接到连接池的请求
- SqlSession 就相当于一个数据库连接(Connection 对象),你可以在一个事务里面执行多条 SQL,
然后通过它的 commit、rollback等方法,提交或者回滚事务。 - 所以它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给 SqlSessionFactory,
否则数据库资源就很快被耗费精光,系统就会瘫痪,所以用 try...catch...finally... 语句来保证其正确关闭。

ResultMap
属性名,字段名不一致
如果POJO同数据库的字段不一致
正常运行会显示不一致的字段为null
User{id=0, name='zjz0', pwd='null'}1.解决方法--别名
<select id="selectUserById" resultType="User">
select id , name , password as pwd from user where id = #{id}
</select>
2.方案二:使用结果集映射->ResultMap 【推荐】
- 注意:
<resultMap id="UserMap" type="User"> 的id
对应<select id="selectUserById" resultMap="UserMap">的resultMap
<resultMap id="UserMap" type="User">
<!-- id为主键 -->
<id column="id" property="id"/>
<!-- column是数据库表的列名 , property是对应实体类的属性名 -->
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap> <select id="selectUserById" resultMap="UserMap">
select id , name , pwd from user where id = #{id}
</select>- 注意:
数据库中,存在一对多,多对一的情况,我们之后会
使用到一些高级的结果集映射,association,collection这些

多表查询
- 在Mybatis-常规操作中 代码地址如下:在mybatis-06中
代码地址
- ------------https://gitee.com/zhangjzm/my-batis.git
Mybatis-基本学习(下)的更多相关文章
- Mybatis架构学习
Mybatis架构学习 MyBatis 是支持定制化 SQL.存储过程以及高级映射的持久层框架.MyBatis 封装了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.可以对配置和原生Map使用 ...
- MyBatis入门学习教程-使用MyBatis对表执行CRUD操作
上一篇MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对use ...
- MyBatis入门学习(二)
在MyBatis入门学习(一)中我们完成了对MyBatis简要的介绍以及简单的入门小项目测试,主要完成对一个用户信息的查询.这一节我们主要来简要的介绍MyBatis框架的增删改查操作,加深对该框架的了 ...
- Spring+SpringMVC+MyBatis深入学习及搭建(二)——MyBatis原始Dao开发和mapper代理开发
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6869133.html 前面有写到Spring+SpringMVC+MyBatis深入学习及搭建(一)——My ...
- Spring+SpringMVC+MyBatis深入学习及搭建(三)——MyBatis全局配置文件解析
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6874672.html 前面有写到Spring+SpringMVC+MyBatis深入学习及搭建(二)——My ...
- Spring+SpringMVC+MyBatis深入学习及搭建(六)——MyBatis关联查询
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6923464.html 前面有将到:Spring+SpringMVC+MyBatis深入学习及搭建(五)--动 ...
- Spring+SpringMVC+MyBatis深入学习及搭建(七)——MyBatis延迟加载
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6953005.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(六)——My ...
- Spring+SpringMVC+MyBatis深入学习及搭建(八)——MyBatis查询缓存
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6956206.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(七)——My ...
- Spring+SpringMVC+MyBatis深入学习及搭建(九)——MyBatis和Spring整合
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6964162.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(八)--My ...
- Spring+SpringMVC+MyBatis深入学习及搭建(十)——MyBatis逆向工程
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6973266.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(九)--My ...
随机推荐
- 一文彻底搞清 Gradle 依赖【转】
来源:曾是放牛娃 www.jianshu.com/p/59fd653a54d2 转自:https://mp.weixin.qq.com/s?__biz=MzA3MDMyMjkzNg==&mid ...
- ContentObserver 内容观察者作用及特点
eg: 1.定义Uri public static Uri KEY_BROWSER_URI = Uri.parse("content://com.android.browser.provid ...
- .NetCore+Envoy+Id4+Dapr+EFCore 构建微服务之Envoy
.NetCore比较流行的微服务应该时是用Ocelot的方式构建微服务,纯配置化,开发量也比较小.但是做过一些项目之后发现这个方式不是很适合,首先它比较笨重,其次不支持gRpc和webSocket通信 ...
- rollup 开发环境搭建
rollup 开发环境搭建 初始化项目使用lerna管理项目 使用npm init 初始化项目 npm init -y 安装lerna并初始化项目 npm install lerna --save-d ...
- git连接远程GitHub仓库详细总结 for HTTPS协议
简单唠叨几句哈.之前工作的时候,由于是在大厂,代码提交.版本管理都是多人协作的,所以公司当时用的git + gerrit来实现代码管理的.当时入职时并不懂git的使用,虽然有大神写好配置git的文档, ...
- 【笔记】numpy.array基础(2)
numpy数组的基本操作 以几个数组为例 使用ndim可以显示出是几维数组 使用shape可以查看元素维度数 使用size可以查看元素个数 对一维数组进行数据访问 对多维数组进行数据访问 切片访问,使 ...
- HTML5(十二)——一文读懂 WebSocket 原理
一.WebSocket 由来 WebSocket 是一个持久化的协议,通过第一次 HTTP Request 建立连接之后,再把通信协议升级成 websocket,保持连接状态,后续的数据交换不需要再重 ...
- [1.6W字]浏览器跨域请求的原理, 以及解决方法(可以纯前端实现) #flight.Archives011
Title/ 浏览器跨域(CrossOrigin)请求的原理, 以及解决方案详细指南 #flight.Archives011 序: 最近看到又有一波新的创作活动了, 官方给出的话题中有一个" ...
- 一文搞懂B树、B-树、B+树
前言 B树和B-树是同一种数据结构,如果不清楚的话,会被面试官忽悠,所以本文介绍两种数据结构,B树和B+树,废话不多数咱们开干. B树 介绍 在计算机科学中,B树是一种自平衡的树,能够保持数据有序.这 ...
- 题解 P5038 [SCOI2012]奇怪的游戏
题解 题目 做这题之前,做了一道叫星际战争的题,很容易想到二分 \(+\) 网络流,那么二分啥呢? 我们先推一下式子,因为是对相邻格子加数,那么可以联想到黑白染色类问题. 设有黑色格子 \(B\) 个 ...