(3)Mybatis————分析dao实现类的执行过程,代理dao的执行过程,常用的标签以及查询语句

1, Mybatis的dao实现类的执行过程

2, 分析代理dao的执行过程

3, Mybatis 连接池与事务深入

4, Mybatis 的动态 SQL 语句

5,Mybatis 多表查询之一对多

6,Mybatis 多表查询之多对多

Mybatis的dao实现类的执行过程
  • PreparedStatement对象它的执行方法

    • execute:它能执行CRUD中的任意-种语句。它的返回值是一个boolean类型,表示是否有结果集。有结果集是true,没有结果集是fasle

    • executeUpdate:它只能执行CUD语句,查询语句无法执行。他的返回值是影响数据库记录的行数

    • executeQuery:它只能执行SELECT语句,无法执行增删改。执行结果封装的结果集ResultSet对象

  • 分析编写dao实现类Mybatis的执行过程:
    在这里插入图片描述

分析代理dao的执行过程

在这里插入图片描述

Mybatis 连接池与事务深入

1,Mybatis 的连接池技术

  • 在 Mybatis 中也有连接池技术,它采用的是自己的连接池技术。在 Mybatismybatis-config.xml 配置文件中,通过<dataSource type="pooled">来实现 Mybatis 中连接池的配置。

  • 在 Mybatis 中我们将它的数据源 dataSource 分为以下几类:

    UNPOOLED:不使用连接池的数据源,采用传统的javax. sql. DataSource规范中的连接池,mybatis中有针对规范的实现

    POOLED :使用连接池的数据源,采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。

    JNDI: 使用 JNDI 实现的数据源,采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样

  • 在这三种数据源中,我们一般采用的是 POOLED 数据源(很多时候我们所说的数据源就是为了更好的管理数据
    库连接,也就是我们所说的连接池技术)。

  • MyBatis 内部分别定义了实现了 java.sql.DataSource 接口的 UnpooledDataSourcePooledDataSource 类来表示 UNPOOLEDPOOLED 类型的数据源。

    • PooledDataSourceUnpooledDataSource 都实现了java.sqlDataSource接口。并且PooledDataSource持有一个UnpooledDataSource的引用 。当PooledDataSource需要创建java.sql.Connection实例对象时。还是通过UnpooledDataSource来创建,PooledDataSource只是提供一种缓存连接池机制。
  • Mybatis 中 DataSource 的存取

    • MyBatis 是通过工厂模式来创建数据源 DataSource 对象的, MyBatis 定义了抽象的工厂接口:org.apache.ibatis.datasource.DataSourceFactory,通过其 getDataSource()方法返回数据源DataSource。
      在这里插入图片描述

2,Mybatis 的事务控制

  • Mybatis 中事务的提交方式,本质上就是调用 JDBC 的 setAutoCommit()来实现事务控制
  • 通过源码分析,设置 session = factory.openSession(true)即可以改成自动提交,
    在这里插入图片描述
  • 此时事务就设置为自动提交了,同样可以实现CUD操作时记录的保存。虽然这也是一种方式,但就编程而言,设置为自动提交方式为 false再根据情况决定是否进行提交,这种方式更常用。因为我们可以根据业务情况来决定提交是否进行提交。
Mybatis 的动态 SQL 语句

1,动态 SQL 之 if 标签

  • 我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。比如在 id 如果不为空时可以根据 id 查询,如果 name 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到

  • 示例代码:

  • 持久层 Dao 接口:

/**
 * 根据用户信息,查询用户列表
 */
List<User> queryByUser(User user);
  • 持久层 Dao 映射配置:
<select id="queryByUser" resultMap="userMap">
    select * from user
    where 1 = 1
    <if test="name != null and name.trim!=''">
        and name = #{name}
    </if>
    <if test="uAddress != null and uAddress.trim!=''">
        and address like concat('%',#{uAddress},'%')
    </if>
</select>

2,动态 SQL 之 where 标签

  • 为了简化上面 where 1=1 的条件拼装,我们可以采用标签来简化开发。
  • 代码示例:
    • 持久层 Dao 映射配置:
<select id="queryByUser" resultMap="userMap">
    select * from user
    <where>
    <if test="name != null and name.trim!=''">
        and name = #{name}
    </if>
    <if test="uAddress != null and uAddress.trim!=''">
        and address like concat('%',#{uAddress},'%')
    </if>
    </where>
</select>

3,动态标签之 foreach 标签

  • 当查询的条件为集合时需要用到 foreach 标签

  • 代码示例:

  • 持久层 Dao 接口:

/**
 * 根据多个用户id,查询用户列表,ids为集合,没有set,get方法,mybatis中需要用if,所以需要用到@Param注解
 */
List<User> queryByListId(@Param("ids")List<Integer> ids);
  • 持久层 Dao 映射 配置:
<select id="queryByListId" resultMap="userMap">
    select * from user
    <where>
        <if test="ids != null and ids.size() > 0">
            <foreach collection="ids" open="id in ( " close=")" item="uid" separator=",">
                #{uid}
            </foreach>
        </if>
    </where>
</select>
  • SQL 语句解析:

    • select * from user where id in (?)

      <foreach>标签用于遍历集合,它的属性:

      collection:代表要遍历的集合元素,注意编写时不要写#{}

      open:代表语句的开始部分

      close:代表结束部分

      item:代表遍历集合的每个元素,生成的变量名

      sperator:代表分隔符

  • 测试类:

@Test
public void queryByListIdTest() {
    List<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    List<User> userList = userDao.queryByListId(list);
    userList.stream().forEach(System.out::println);
}

4,Mybatis 中简化编写的 SQL 片段

  • Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。

  • 示例代码:

  • 定义代码片段:

<!-- 抽取重复的语句代码片段 -->
<sql id="defaultSql">
    select * from user
</sql>
  • 引用代码片段:
<!-- 配置查询所有操作 -->
<select id="findAll" resultType="user">
<include refid="defaultSql"></include>
</select>
Mybatis 多表查询之一对多

1,一对一查询

在这里插入图片描述

  • 因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询:
  • Account 实体:
/**
 * 账户实体类
 */
public class Account implements Serializable {

    private Integer id;
    private Integer uid;
    private Double money;

    //从表实体应该包含一个主表实体的对象引用
    private User user;
}
  • User 实体:
public class User implements Serializable {

    private Integer id;
    private String username;
    private String address;
    private String sex;
    private Date birthday;
}
  • AccountDao 接口中的方法:
/**
 * 账户的持久层接口
 */
public interface AccountDao {
    /**
     * 查询所有账户,同时获取账户的所属用户名称以及它的地址信息
     * @return
     */
    List<Account> findAll();
}
  • AccountDao.xml 文件:
<mapper namespace="com.zhou.dao.AccountDao">

    <!-- 定义封装account和user的resultMap -->
    <resultMap id="accountUserMap" type="account">
        <id property="id" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!-- 一对一的关系映射:配置封装user的内容-->
        <association property="user" column="uid" javaType="user">
            <id property="id" column="id"></id>
            <result column="username" property="username"></result>
            <result column="address" property="address"></result>
            <result column="sex" property="sex"></result>
            <result column="birthday" property="birthday"></result>
        </association>
    </resultMap>

    <select id="findAll" resultMap="accountUserMap">
        select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id
    </select>
</mapper>

2,一对多查询

  • 用户信息和他的账户信息为一对多关系:

  • User 实体类:

public class User implements Serializable {

    private Integer id;
    private String username;
    private String address;
    private String sex;
    private Date birthday;

    //一对多关系映射:主表实体应该包含从表实体的集合引用
    private List<Account> accounts;
}
  • 用户持久层 Dao 接口 中加入查询方法:
/**
* 查询所有用户,同时获取出每个用户下的所有账户信息
*/
List<User> findAll();
  • 用户持久层 Dao 映射文件 配置:
<resultMap id="userMap" type="user">
    <id property="id" column="id"></id>
    <result column="username" property="username"></result>
    <result column="address" property="address"></result>
    <result column="sex" property="sex"></result>
    <result column="birthday" property="birthday"></result>
    <!-- collection 是用于建立一对多中集合属性的对应关系ofType 用于指定集合元素的数据类型 -->
    <collection property="accounts" ofType="account">
    <id column="aid" property="id"/>
    <result column="uid" property="uid"/>
    <result column="money" property="money"/>
    </collection>
</resultMap>

<select id="queryAll" resultMap="userMap">
    select u.*,a.id as aid ,a.uid,a.money from user u left join account a on u.id =a.uid
</select>
  • 测试方法:
@Test
public void queryAllTests() {
    List<User> users = userDao.queryAll();
    for(User user : users) {
        System.out.println(user);
        System.out.println(user.getAccounts());
    }
}
Mybatis 多表查询之多对多
  • 用户与角色的多对多关系模型如下:
    在这里插入图片描述

  • 实现查询所有对象并且加载它所分配的用户信息:

  • Role实体类:

@ToString
@Data
public class Role implements Serializable {

    private Integer roleId;
    private String roleName;
    private String roleDesc;

    //多对多的关系映射:一个角色可以赋予多个用户
    private List<User> users;
}
  • 编写 Role 持久层 接口:
public interface IRoleDao {
    /**
     * 查询所有角色
     */
    List<Role> queryRoleAll();
}
  • 编写映射文件:
<resultMap id="roleMap" type="role">
    <id property="roleId" column="rid"></id>
    <result property="roleName" column="role_name"></result>
    <result property="roleDesc" column="role_desc"></result>
    <collection property="users" ofType="user">
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
        <result column="address" property="address"></result>
        <result column="sex" property="sex"></result>
        <result column="birthday" property="birthday"></result>
    </collection>
</resultMap>

<select id="queryRoleAll" resultMap="roleMap">
    select u.*,r.id as rid,r.role_name,r.role_desc from role r
    left join user_role ur on r.id = ur.rid
    left join user u on u.id = ur.uid
</select>
  • 编写测试类
@Test
public void queryRoleAllTest() {
    List<Role> roles = roleDao.queryRoleAll();
	roles.stream().forEach(System.out::println);
}

下一章,(4)Mybatis————JNDI数据源的使用,延迟加载,缓存以及使用注解开发

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值