Mybatis中连接池、事务和多表查询
-
Mybatis中的连接池:
- mybatis中数据源的分类:(从上面一篇的文章中能够得知Mybatis中数据源分为三种)
- Mybatis中的数据源的配置:数据源的配置常常是在SqlMapConfig.xml 文件中:具体的配置如下:
mybatis在初始化的过程中,会根据不同的<datasource>的type属性来创建相应类型的数据源datasource,使用的模式工厂模式 Mybatis定义了抽象接口,使用getDataSource方法来将数据源返回。<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>
- type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
- type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例
- type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
- mybatis中的连接获取的过程分析:得知只有要创建SqlSession对象且要执行SQL语句的时候才或调用datasource对象来创建连接对象,这样的方式带来的好处就是,数据库连接是非常重要的,只有用的时候才会获取连接,不用的时候就会立即将连接归还到池中,节省了数据库连接的资源。
- mybatis中数据源的分类:(从上面一篇的文章中能够得知Mybatis中数据源分为三种)
-
Mybatis中的事务控制
- jdbc中开启事务的方式:使用的是Connection对象的setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
- mybatis中开启事务的两种方式:(前面的文章已经提到过这里就不多说了,但是底层上其实还是jdbc中的setAutoCommit 方法)
- 一种是session对象的commit()方法
- 另一种是SqlSessionFactory对象的openSession(true)
【注意】这两种方式相比较而言:使用上面的方式较为合理一些,可以根据业务的不同而决定是否是提交。
-
Mybatis中的动态SQL语句(Mybatis中实现的SQL都是较为简单的 实际的生产环境中,SQL语句中传入的条件是不一定的 因此动态的SQL就非常的重要。)
- 动态SQL的官方文档
- 动态SQL使用的标签
-
if 标签:有时候执行SQL的时候传入的条件有时候有有时候没有 这样的时候使用if标签来进行判断 使用的步骤:
-
首先在用户层接口dao中添加方法,通过用户的信息来查询用户的列表 List<User> findByUser(User user);
-
进行持久层的到映射配置
<!--注意的是:这里的user注册了别名 没有注册需要使用全限定类名--> <select id="findByUser" resultType="user" parameterType="user"> select * from user where 1=1 <!--注意的是:test属性中写的是对象的属性名,如果是包装类的对象需要使用OGNL表达式的写法--> <if test="username!=null and username != '' "> and username like #{username} </if> <if test="address != null"> and / or address like #{address} </if> </select>
【注意】:1 where 1=1 的作用:是为了避免where 关键字后面的第一个词直接就是 “and”而导致语法错误,是为了后面附加and …方便程序逻辑处理用的。(这一点也非常的重要) 2 test属性中与和或的写法是使用and 和 or 不能使用&& 和 ||
-
简化where 1=1的条件拼装方式(使用where标签将if标签进行包裹):持久层映射配置
<!-- 根据用户信息查询 --> <!--注意的是:这里的user注册了别名 没有注册需要使用全限定类名--> <select id="findByUser" resultType="user" parameterType="user"> select * from user where 1=1 <where> <if test="username!=null and username != '' "> and username like #{username} </if> <if test="address != null"> and address like #{address} </if> </where> </select>
-
在写sql语句过程中 碰到一些sql片段反复出现如:select * from user 将这些sql片段进行抽取,从而达到sql片段重复使用的目的:使用的标签是sql标签 导入标签使用include标签:id属性表示的是唯一的标识 sql标签能够进行嵌套的引用
<!--使用sql标签进行抽取--> <sql id="defaultUser"> select * from user </sql> <!--使用include标签进行导入 refid:就是引用标签的id--> <include refid="defaultUser"></include>
-
-
choose 标签:if 标签提供了基本的条件判断,但是它无法实现
if. . . else if ... else ...
的逻辑,要想实现这样的逻辑,就需要用到choose when otherwise
标签 也就是说 条件之间有优先级进行判断使用choose when otherwise
的时候逻辑要严密,避免由于某些值出现问题导致 SQL出错(如果没有 otherwise 这个限制条件,所有的用户都会被查询出来)<select id="selectByidOrUserName" resultType=" tk.mybatis.simple.m0del. SysUser" > select id, user_name userName , user_password userPassword, user_email userEmail , user_info userinfo , head_img headimg , create_time createTime from sys_user where 1 = 1 <choose> <when test="id != null" > and id= #{id} </when> <when test="userName != null and userName !=''"> and user name = #{userName} </when> <otherwise> and 1 = 2 </otherwise> </choose> </select>
-
foreach标签:进行范围查询时,就要将一个集合中的值,作为参数动态添加进来,此时就需要使用foreach标签:使用的步骤
-
和if标签一样进行dao进行接口方法的添加,编写参数的类型实体类
public class QueryVo { private User user; private List<Integer> ids; public List<Integer> getIds() { return ids; } public void setIds(List<Integer> ids) { this.ids = ids; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
-
然后配置映射文件:
<select id="findInIds" resultType="user" parameterType="queryVo"> <!-- select * from user where id in (1,2,3,4,5); --> <include refid="defaultSql"></include> <where> <if test="ids != null and ids.size() > 0"> <foreach collection="ids" open="id in ( " close=")" item="uid" separator=","> #{uid} </foreach> </if> </where> </select>
-
foreach标签中的属性详解:
- foreach元素的属性主要有 item、index、 collection、open、separator、close:
- collection 表示要做foreach循环的对象,注意在编写的时候不要加上#{} sql只接收一个数组参数,这时sql解析参数的名称mybatis固定为array(或则是 list map),如果数组是通过一个pojo传递到sql则参数的名称为pojo中的属性名。
- item 表示集合中每一个元素或者该集合的对象,支持对象.属性的方式获取属性。
- index 表示循环的下标,从0开始 当选代循环的对象是 Map类型时,这个值为 Map key (键值)
- open 表示以什么开始
- close表示以什么结束
- separator 表示每次进行迭代之间以什么符号作为分隔符
- foreach元素的属性主要有 item、index、 collection、open、separator、close:
-
-
where set trim 标签:
-
where 标签的作用:如果该标签包含的元素中有返回值 就插入 where 如果 where后面字符串是以 AND OR 开头的就将它们剔除 简单的说就是代替where 1=1
<where> <if test="username != null and username !=''"> and username = #{username} </if> <if test="sex != null"> and sex = #{sex} </if> </where>
-
set 标签的作用:如果该标签包含的元素中有返回值,就插入 set 如果 set 后面的字符串是 以逗号结尾的,就将这个逗号剔除 需要注意的是set 标签的用法中 SQL 后面的逗号没有问题了,但是如果 set 元素中没有内容,照样会出现 SQL 错误,所以为了避免错误产生,类似 id = #{id }这样必然存在的赋值仍然有保留的必要
<set> <if test="userName != null and userName !=''"> user name= #{userName} , </ if> </set>
-
trim 标签:where set 标签 的功能都可以用 trim 标签来实现,并且在底层就是通过TrimSqlNode 现的
where 标签对应 trim 的实现如下:<trim prefix="WHERE" prefixOverrides="AND |OR " > ... </trim>
set 标签对应 trim 实现如下:
<trim prefix="SET" suffixOverrides=", " > </trim>
- trim 标的属性:
- prefix :当 trim 元素内包含内容时,会给内容增加 prefix 指定的前缀。
- prefixOverrides :当 trim 元素内包含内容时,会把内容中匹配的前缀字符串去掉。
- suffix :当 trim 元素内包含内容时,会给内容增加 suffix 指定的后缀。
- suffixOverrides :当 trim 元素内包含内容时,会把内容中匹配的后缀字符串去掉
- trim 标的属性:
-
-
bind 标签:bind 标签可以使用 OGNL 表达式创建一个变量井将其绑定到上下文中 如使用 concat 函数连接字符串,在 MySQL 中,这个函数支持多个参数,但在 Oracle 中只支持两个参数。由于不 同数据库之间的语法差异 ,如果更换数据库,有些 SQL 语句可能就需要重写。针对这种情况,可以使用 bind 标签来避免由于更换数据库带来的一些麻烦 使用 bind 拼接字符串不仅可以避免因更换数据库而修改SQL ,也能预防 SQL 注入
<if test="userNarne != null and userNarne !=''"> <bind name="userNarneLike" value= "'%'+userName+'%'"/> and username like #{userNarneLike} </if>
bind标签中的属性:两个属性都是必须项:
name
为绑定到上下文的变量名value
OGNL表达式
-
-
OGNL 用法:MyBatis 的动态 SQL 和${}形式的参数中都用到了 OGNL 表达式 所以我们有必要了解OGNL 的简单用法 MyBatis 常用的 OGNL 表达式如下:常用的就是前四种
- el or e2
- el and e2
- el == e2 el eq e2
- el ! = e2 el neq e2
- el lt e2 :小于
- el lte e2 :小于等于,其他表示为 gt (大于)、 gte (大于等于)
- el + e2 e2 1/e2 1 - e2 e2
- ! not :非,取反
- e.method(args) 调用对象方法
- e.property 对象属性值
- el[ e2 按索引取值( List 、数组和 Map)
- @class@method(args ):调用类的静态方法
- @class@field :调用类的静态字段值
-
Mybatis中的多表查询:
-
多表关系的概述:所谓的多表关联,就是表结构中存在多对一,一对多的现象,当然也存在多对多的关系。在实际的工作中,经常存在多表关联的存在,也就是说外键的存在。比如说:商品表goods,会关联一个分类表,将每个商品进行分类处理。
-
mybatis中的多对一(一对一)关系的实现:两种方式:
- 定义专门的po类型作为输出类型,定义SQL语句中查询出的结果集的所有的字段这样的方式较为简单,但是这样的方式造成的结果就是会创建多种的实体类,不是非常的好用,这里不详细说明。
- 就是使用resultMap来映射一对一的查询结果:获取的是一个对象
属性详解:<!-- 建立对应关系 --> <resultMap type="account" id="accountMap"> <id column="aid" property="id"/> <result column="uid" property="uid"/> <result column="money" property="money"/> <!-- 它是用于指定从表方的引用实体属性的 --> <association property="user" column="uid" javaType="user"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <result column="address" property="address"/> </association> </resultMap>
- property:映射数据库列的字段或属性
- colum:数据库的列名或者列标签别名
- javaType:完整java类名或别名
- jdbcType支持的JDBC类型列表列出的JDBC类型 这个属性只在insert,update或delete的时候针对允许空的列有用。
- resultMap: 一个可以映射联合嵌套结果集到一个适合的对象视图上的ResultMap 这是一个替代的方式去调用另一个select语句
-
mybatis中的一对多(多对多)的实现方式:使用的是resultMap形式 获取的是对象的集合
<resultMap type="user" id="userMap"> <id column="id" property="id"></id> <result column="username" property="username"/> <result column="address" property="address"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <!-- collection 是用于建立一对多中集合属性的对应关系ofType 用于指定集合元素的数据类型--> <collection property="accounts" ofType="account"> <id column="aid" property="id"/> <result column="uid" property="uid"/> <result column="money" property="money"/> </collection> </resultMap>
属性详解:
- property:指定的是集合的属性
- ofType 用于指定集合元素的数据类型
-