JavaWeb框架 - Mybatis04

Mybatis中连接池、事务和多表查询

  1. Mybatis中的连接池:

    • mybatis中数据源的分类:(从上面一篇的文章中能够得知Mybatis中数据源分为三种)
      在这里插入图片描述
    • Mybatis中的数据源的配置:数据源的配置常常是在SqlMapConfig.xml 文件中:具体的配置如下:
       <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>
      
      mybatis在初始化的过程中,会根据不同的<datasource>的type属性来创建相应类型的数据源datasource,使用的模式工厂模式 Mybatis定义了抽象接口,使用getDataSource方法来将数据源返回。
      • type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
      • type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例
      • type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
    • mybatis中的连接获取的过程分析:得知只有要创建SqlSession对象且要执行SQL语句的时候才或调用datasource对象来创建连接对象,这样的方式带来的好处就是,数据库连接是非常重要的,只有用的时候才会获取连接,不用的时候就会立即将连接归还到池中,节省了数据库连接的资源。
      在这里插入图片描述
  2. Mybatis中的事务控制

    • jdbc中开启事务的方式:使用的是Connection对象的setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
    • mybatis中开启事务的两种方式:(前面的文章已经提到过这里就不多说了,但是底层上其实还是jdbc中的setAutoCommit 方法)
      • 一种是session对象的commit()方法
      • 另一种是SqlSessionFactory对象的openSession(true)
        【注意】这两种方式相比较而言:使用上面的方式较为合理一些,可以根据业务的不同而决定是否是提交。
  3. 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 表示每次进行迭代之间以什么符号作为分隔符
      • 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 元素内包含内容时,会把内容中匹配的后缀字符串去掉
      • 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表达式
  4. OGNL 用法:MyBatis 的动态 SQL 和${}形式的参数中都用到了 OGNL 表达式 所以我们有必要了解OGNL 的简单用法 MyBatis 常用的 OGNL 表达式如下:常用的就是前四种

    1. el or e2
    2. el and e2
    3. el == e2 el eq e2
    4. el ! = e2 el neq e2
    5. el lt e2 :小于
    6. el lte e2 :小于等于,其他表示为 gt (大于)、 gte (大于等于)
    7. el + e2 e2 1/e2 1 - e2 e2
    8. ! not :非,取反
    9. e.method(args) 调用对象方法
    10. e.property 对象属性值
    11. el[ e2 按索引取值( List 、数组和 Map)
    12. @class@method(args ):调用类的静态方法
    13. @class@field :调用类的静态字段值
  5. 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 用于指定集合元素的数据类型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上山打卤面

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值