Mybatis重点

一、Mybatis有三种基本的Executor执行器:

          SimpleExecutor、ReuseExecutor、BatchExecutor。

SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。

BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。

Mybatis中如何指定使用哪一种Executor执行器?

答:在Mybatis配置文件中,可以指定默认的ExecutorType执行器类型,也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型参数。

 

SqlSession根据Statement ID, 在mybatis配置对象Configuration中获取到对应的MappedStatement对象,然后调用mybatis执行器来执行具体的操作。

                      

 

二、缓存

一级缓存:

                           

 

1、一级缓存的生命周期有多长?

  a、MyBatis在开启一个数据库会话时,会 创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象。Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。

  b、如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用。

  c、如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用。

  d、SqlSession中执行了任何一个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用

2、怎么判断某两次查询是完全相同的查询?

  mybatis认为,对于两次查询,如果以下条件都完全一样,那么就认为它们是完全相同的两次查询。

  2.1 传入的statementId

  2.2 查询时要求的结果集中的结果范围

  2.3. 这次查询所产生的最终要传递给JDBC java.sql.Preparedstatement的Sql语句字符串(boundSql.getSql() )

  2.4 传递给java.sql.Statement要设置的参数值

二级缓存:

                           

SqlSessionFactory层面上的二级缓存默认是不开启的,二级缓存的开启需要进行配置,实现二级缓存的时候,MyBatis要求返回的POJO必须是可序列化的。 也就是要求实现Serializable接口,配置方法很简单,只需要在映射XML文件配置就可以开启缓存了<cache/>,如果我们配置了二级缓存就意味着:

 

 

  • 映射语句文件中的所有select语句将会被缓存。
  • 映射语句文件中的所欲insert、update和delete语句会刷新缓存。
  • 缓存会使用默认的Least Recently Used(LRU,最近最少使用的)算法来收回。
  • 根据时间表,比如No Flush Interval,(CNFI没有刷新间隔),缓存不会以任何时间顺序来刷新。
  • 缓存会存储列表集合或对象(无论查询方法返回什么)的1024个引用
  • 缓存会被视为是read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全的被调用者修改,不干扰其他调用者或线程所做的潜在修改。

 

三、ResultMap和ResultType在使用中的区别:

resultType:当使用resultType做SQL语句返回结果类型处理时,对于SQL语句查询出的字段在相应的pojo中必须有和它相同的字段对应,而resultType中的内容就是pojo在本项目中的位置。

resultMap:当使用resultMap做SQL语句返回结果类型处理时,通常需要在mapper.xml中定义resultMap进行pojo和相应表字段的对应,<resultMap> 元素包含了一些子元素,结构如下:

<resultMap id="" type=""> <constructor><!-- 类再实例化时用来注入结果到构造方法 --> <idArg/><!-- ID参数,结果为ID --> <arg/><!-- 注入到构造方法的一个普通结果 --> </constructor> <id/><!-- 用于表示哪个列是主键 --> <result/><!-- 注入到字段或JavaBean属性的普通结果 --> <association property=""/><!-- 用于一对一关联 --> <collection property=""/><!-- 用于一对多、多对多关联 --> <discriminator javaType=""><!-- 使用结果值来决定使用哪个结果映射 --> <case value=""/><!-- 基于某些值的结果映射 --> </discriminator> </resultMap>

四、transactionManager(事务管理器)

<transactionManager type="JDBC"/>

<transactionManager type="MANAGED"/>

JDBC 使用 JdbcTransactionFactory 生成的 JdbcTransaction 对象实现。它是以 JDBC 的方式对数据库的提交和回滚进行操作。

MANAGED 使用 ManagedTransactionFactory 生成的 ManagedTransaction 对象实现。它的提交和回滚方法不用任何操作,而是把事务交给容器处理。在默认情况下,它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。

五、environment 数据源环境

1. UNPOOLED

UNPOOLED 采用非数据库池的管理方式,每次请求都会打开一个新的数据库连接,所以创建会比较慢。在一些对性能没有很高要求的场合可以使用它。

 

对有些数据库而言,使用连接池并不重要,那么它也是一个比较理想的选择。UNPOOLED 类型的数据源可以配置以下几种属性:

  • driver 数据库驱动名,比如 MySQL 的 com.mysql.jdbc.Driver。
  • url 连接数据库的 URL。
  • username 用户名。
  • password 密码。
  • defaultTransactionIsolationLevel 默认的连接事务隔离级别,关于隔离级别,后面教程中会讨论。

 

传递属性给数据库驱动也是一个可选项,注意属性的前缀为“driver.”,例如 driver.encoding=UTF8。它会通过 DriverManager.getConnection(url,driverProperties)方法传递值为 UTF8 的 encoding 属性给数据库驱动。

2. POOLED

数据源 POOLED 利用“池”的概念将 JDBC 的 Connection 对象组织起来,它开始会有一些空置,并且已经连接好的数据库连接,所以请求时,无须再建立和验证,省去了创建新的连接实例时所必需的初始化和认证时间。它还控制最大连接数,避免过多的连接导致系统瓶颈。

3. JNDI

数据源 JNDI 的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。这种数据源配置只需要两个属性:

1)initial_context

用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。initial_context 是个可选属性,如果忽略,那么 data_source 属性将会直接从 InitialContext 中寻找。

2)data_source

是引用数据源实例位置上下文的路径。当提供 initial_context 配置时,data_source 会在其返回的上下文中进行查找;当没有提供 initial_context 时,data_source 直接在 InitialContext 中查找。

 

与其他数据源配置类似,它可以通过添加前缀“env.”直接把属性传递给初始上下文(InitialContext)。比如 env.encoding=UTF8,就会在初始上下文实例化时往它的构造方法传递值为 UTF8 的 encoding 属性。

六、级联查询

1、一对一级联关系

在 MyBatis 中,通过 <resultMap> 元素的子元素 <association> 处理这种一对一级联关系。

 

在 <association> 元素中通常使用以下属性。

  • property:指定映射到实体类的对象属性。
  • column:指定表中对应的字段(即查询返回的列名)。
  • javaType:指定映射到实体对象属性的类型。
  • select:指定引入嵌套查询的子 SQL 语句,该属性用于关联映射中的嵌套查询。

(1)一对一根据id查询个人信息:级联查询的第一种方法(嵌套查询,执行两个SQL语句)

<resultMap type="com.po.Person" id="cardAndPerson1">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
        <!-- 一对一级联查询-->
        <association property="card" column="idcard_id" javaType="com.po.Idcard"
        select="com.dao.IdCardDao.selectCodeByld"/>
    </resultMap>
    <select id="selectPersonById1" parameterType="Integer" resultMap=
    "cardAndPerson1">
        select * from person where id=#{id}
    </select>

(2)一对一根据id查询个人信息:级联查询的第二种方法(嵌套结果,执行一个SQL语句)

 <resultMap type="com.po.Person" id="cardAndPerson2">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
        <!-- 一对一级联查询-->
        <association property="card" javaType="com.po.Idcard">
            <id property="id" column="idcard_id"/>
            <result property="code" column="code"/>
        </association>
    </resultMap>
    <select id="selectPersonById2" parameterType="Integer" resultMap= "cardAndPerson2">
        select p.*,ic.code
        from person p, idcard ic
        where p.idcard_id=ic.id and p.id=#{id}
    </select>

(3)一对一根据id查询个人信息:连接查询(使用POJO存储结果)

 <select id="selectPersonById3" parameterType="Integer" resultType= "com.pojo.SelectPersonById">
        select p.*,ic.code
        from person p, idcard ic
        where p.idcard_id = ic.id and p.id=#{id}
    </select>

 

2、一对多级联查询

(1)一对多 根据uid查询用户及其关联的订单信息:级联查询的第一种方法(嵌套查询)

<resultMap type="com.po.MyUser" id="userAndOrders1">
        <id property="uid" column="uid" />
        <result property="uname" column="uname" />
        <result property="usex" column="usex" />
        <!-- 一对多级联查询,ofType表示集合中的元素类型,将uid传递给selectOrdersByld -->
        <collection property="ordersList" ofType="com.po.Orders"
            column="uid" select="com.dao.OrdersDao.selectOrdersByld" />
    </resultMap>
    <select id="selectUserOrdersById1" parameterType="Integer"
        resultMap="userAndOrders1">
        select * from user where uid = #{id}
    </select>

(2)一对多根据uid查询用户及其关联的订单信息:级联查询的第二种方法(嵌套结果)

<resultMap type="com.po.MyUser" id="userAndOrders2">
        <id property="uid" column="uid" />
        <result property="uname" column="uname" />
        <result property="usex" column="usex" />
        <!-- 对多级联查询,ofType表示集合中的元素类型 -->
        <collection property="ordersList" ofType="com.po.Orders">
            <id property="id" column="id" />
            <result property="ordersn" column="ordersn" />
        </collection>
    </resultMap>
    <select id="selectUserOrdersById2" parameterType="Integer"
        resultMap="userAndOrders2">
        select u.*,o.id, o.ordersn from user u, orders o where u.uid
        = o.user_id and
        u.uid=#{id}
    </select>

(3)一对多 根据uid查询用户及其关联的订单信息:连接查询(使用POJO存储结果)

 <select id="selectUserOrdersById3" parameterType="Integer"
        resultType="com.pojo.SelectUserOrdersById">
        select u.*, o.id, o.ordersn from user u, orders o where
        u.uid = o.user_id
        and u.uid=#{id}
    </select>

3、多对多查询

<resultMap type="article" id="baseArticleResultMap">
		<id column="id" property="articleId"/>
		<result column="NAME" property="name"/>
		<result column="price" property="price"/>
		<result column="remark" property="remark"/>
	</resultMap>
	<resultMap type="article" id="findArtcleByIdResultMap" extends="baseArticleResultMap">
		<collection property="orders" javaType="ArrayList"
			ofType="com.gec.domain.Article" column="id"
			select="com.gec.mapper.OrderMapper.findOrderByArticleId"
		>
		</collection>
	</resultMap>
	<!-- 根据订单id查询商品 -->
	<select id="findArtcleByOrderId" resultMap="baseArticleResultMap">
		select * from tb_article  where id 
		in (select article_id from tb_item where order_id=#{id}) 
	</select>
	<select id="findArtcleById" resultMap="findArtcleByIdResultMap">
		select * from tb_article  where id=#{id}
	</select>
</mapper>

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值