MyBatis 3

第三天

Mybatis 连接池与事务控制深入
 	Mybatis 中连接池使用及分析
 	Mybatis 的事务控制分析
Mybatis 的动态 SQL 语句
	mappers配置文件中的几个标签
		<if>
		<where>
		<foreach>
		<sql>
Mybatis 多表操作
	一对一
	一对多
	多对多

Mybatis 连接池与事务深入

Mybatis 连接池的分类

在 Mybatis 中也有连接池技术,但是它采用的是自己的连接池技术。在 Mybatis 的 SqlMapConfig.xml 配置文件中,通过来实现 Mybatis 中连接池的配置

 Mybatis 数据源分为三类:
	UNPOOLED:不使用连接池的数据源	
		Mybatis实现了java.sql.DataSource 接口的UnpooledDataSource 类,无连接池思想。
	POOLED:使用连接池的数据源	
		Mybatis实现了java.sql.DataSource 接口的PooledDataSource 类
	JNDI :使用JNDI 实现的数据源
		采用服务器的JNDI技术实现来获取DataSource,不同的服务器拿到的DataSource是不一样的
		注意:如果不是web或者maven的war工程是不能使用的
		tomcat服务器采用的连接池是dbcp连接池

连接池:用于存储连接的一个容器,容器其实就是一个集合对象,该集合必须是线程安全的,不能俩个线程拿到同一连接,该集合必须实现队列特性,先进先出。mybatis连接池采用的是自己的连接池技术,具体可以查看源码UnpooledDataSourcpe、PooledDataSource

Mybatis 的事务控制

Mybatis 框架因为是对 JDBC 的封装,所以Mybatis 框架的事务控制方式中事务的提交方式,本质上就是调用 JDBC 的 setAutoCommit()来实现事务控制。

Mybatis 的动态 SQL 语句

if标签

的多条件组合查询:根据实体类的不同取值,使用不同的 SQL 语句来进行查询。比如在 id 如果不为空时可以根据 id 查询,如果 username 不同空时还要加入用户名作为条件


    /**
     * 根据传入的参数条件查询
     * @param user 查询条件:有可能有用户名,或者性别...不确定性
     */
    List<User> findByCondition(User user);

	select id="findByCondition" resultType="user" parameterType="user">
        select * from USER where 1=1
        <if test="username != null">
            and username = #{username}
        </if>
        <if test="sex != null">
            and sex = #{sex}
        </if>
    </select>

	@Test
    public void testFindByCondition() {
        User user = new User();
        user.setUsername("老王");
        //user.setSex("男");
        List<User> list = dao.findByCondition(user);
        for (User u : list) {
            System.out.println(u);
        }
    }
where标签

同标签:只需要修改映射文件:

<select id="findByCondition" resultType="user" parameterType="user">
        select * from USER
        <where>
            <if test="username != null">
                and username = #{username}
            </if>
            <if test="sex != null">
                and sex = #{sex}
            </if>
        </where>
</select>
foreach标签

传入多个 id 查询用户信息,用下边两个 sql 实现:
SELECT * FROM USER WHERE username LIKE ‘%张%’ AND (id =10 OR id =89 OR id=16)
SELECT * FROM USER WHERE username LIKE ‘%张%’ AND id IN (10,89,16)
这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来.

package domain;

import java.util.List;

/**
 * @author: Lee
 * @create: 2020-11-15 13:03
 * @description: pojo对象
 **/
public class QueryVo {
    private User user;
    private List<Integer> ids;

    public User getUser() {
        return user;
    }

    public List<Integer> getIds() {
        return ids;
    }

    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }

    public void setUser(User user) {

        this.user = user;
    }
}


  	 /**
     * 根据QueryVo中的ids集合条件实现范围查询
     * @param vo
     * @return
     */
    List<User> findInIds(QueryVo vo);

	<select id="findInIds" parameterType="QueryVo" resultType="user">
        select * from USER
        <where>
            <if test="ids!=null and ids.size()>0">
                <foreach collection="ids" open="and id in (" close=")" item="id" separator=",">
                    #{id}<!--这个值和item的名称需要一致-->
                </foreach>
            </if>
        </where>
    </select>

	@Test
    public void testFindInIds() {
        QueryVo vo = new QueryVo();
        List<Integer> idList = new ArrayList<Integer>();
        idList.add(41);
        idList.add(42);
        idList.add(46);
        vo.setIds(idList);
        List<User> userList = dao.findInIds(vo);
        for (User user : userList) {
            System.out.println(user);
        }
    }
<foreach>标签用于遍历集合,它的属性:
collection:代表要遍历的集合元素,注意编写时不要写#{}
open:代表语句的开始部分
close:代表结束部分
Mybatis 中简化编写的 SQL 片段

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

定义代码片段
<!-- 在映射文件中,抽取重复的语句代码片段 -->
	<sql id="defaultSql">
		select * from user
	</sql>
引用代码片段
<!-- 配置查询所有操作 -->
<select id="findAll" resultType="user">
	<include refid="defaultSql"></include>
</select>
<!-- 根据 id 查询 -->
<select id="findById" resultType="user" parameterType="int">
	<include refid="defaultSql"></include>
	where id = #{uid}
</select>

Mybatis 多表查询之一对多

一对一查询(多对一)
需求
	查询所有账户信息,关联查询下单用户信息。
注意:
	因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。如
果从用户信息出发查询用户下的账户信息则为一对多查询,因为一个用户可以有多个账户。

创建实体类对象使需要实现序列化接口:实现序列化的对象才可以在数据库和文件系统写入,也可以用于网络传输

可以针对查询创建po类作为返回值类型;也可以使用 resultMap,定义专门的 resultMap 用于映射一对一查询结果。

User

package domain;

import java.io.Serializable;
import java.util.Date;

/**
 * @author: Lee
 * @create: 2020-11-13 18:52
 * @description:
 **/
public class User implements Serializable {
    private int id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public User() {
    }

    public User(int id, String username, Date birthday, String sex, String address) {
        this.id = id;
        this.username = username;
        this.birthday = birthday;
        this.sex = sex;
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

Account

package domain;

import java.io.Serializable;

/**
 * @author: Lee
 * @create: 2020-11-16 12:55
 * @description:
 **/
public class Account implements Serializable {
    private Integer id;
    private Integer uid;
    private Double money;

    private User user;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", uid=" + uid +
                ", money=" + money +
                '}';
    }
}

AccountDao.xml

<?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE mapper
                PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.AccountDao">
    <!--一对一-->
    <!--定义主表account封装从表user返回类型-->
    <resultMap id="accountUserMap" type="account">
    	<!--此处的resultMap的配置和下述的列别名应该同步-->
        <id property="id" column="aid"/>
        <result property="uid" column="uid"/>
        <result property="money" column="money"/>
        <!--一对一的关系映射,配置封装user的内容-->
        <association property="user" javaType="user">
            <id property="id" column="id"/>
            <result property="username" column="username"/>
            <result property="birthday" column="birthday"/>
            <result property="sex" column="sex"/>
            <result property="address" column="address"/>
        </association>
    </resultMap>
    <select id="findAll" resultMap="accountUserMap">
    	<!--此处的列别名和上述的resultMap的配置应该同步-->
        select u.* ,a.id  aid,a.uid,a.money from user as u ,account as a where u.id=a.uid
    </select>
</mapper>
一对多查询
需求:
	查询所有用户信息及用户关联的账户信息。
分析:
	用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息
查询出来,我们想到了左外连接查询比较合适。

Account如上
User

package domain;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * @author: Lee
 * @create: 2020-11-13 18:52
 * @description:
 **/
public class User implements Serializable {
    private int id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    //一对多关系映射,主表实体包含从表实体的集合引用
    private List<Account> accounts;

    public User() {
    }

    public User(int id, String username, Date birthday, String sex, String address) {
        this.id = id;
        this.username = username;
        this.birthday = birthday;
        this.sex = sex;
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public List<Account> getAccounts() {
        return accounts;
    }

    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

UserDao.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.UserDao">
    <!--一对多-->
    <!--定义主表user封装从表account集合返回类型-->
    <resultMap id="userAccountMap" type="user">
        <id property="id" column="id" />
        <result property="username" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
        <!--一对多的关系映射,配置封装accounts集合对象的内容-->
        <collection property="accounts" ofType="account">
            <id property="id" column="aid"/>
            <result property="uid" column="uid"/>
            <result property="money" column="money"/>
        </collection>
    </resultMap>
    <select id="findAll" resultMap="userAccountMap">
        select u.*,a.id aid,a.uid,a.money from user u left outer join account a  on u.id=a.uid
    </select>

</mapper>

Mybatis 多表查询之多对多

用户与角色的多对多关系模型在数据库中是需要使用中间表(包含各自的主键)

数据库架构器

需求:
	实现查询所有角色并且加载它所分配的用户信息。
分析:
	查询角色我们需要用到Role表,但角色分配的用户的信息我们并不能直接找到用户信息,而是要通过中间表(USER_ROLE 表)才能关联到用户信息。

RoleDao

package dao;

import domain.Role;

import java.util.List;

/**
 * @author: Lee
 * @create: 2020-11-16 22:42
 * @description:
 **/
public interface RoleDao {
    /**
     * 查询所有角色
     * @return
     */
    List<Role> findAll();
}

Role

package domain;

import java.io.Serializable;
import java.util.List;

/**
 * @author: Lee
 * @create: 2020-11-16 22:39
 * @description:
 **/
public class Role implements Serializable {
    private Integer id;
    private String roleName;
    private String roleDesc;

    //多对多的关系映射,一个角色可以赋予多个用户
    private List<User> users;
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public String getRoleDesc() {
        return roleDesc;
    }

    public void setRoleDesc(String roleDesc) {
        this.roleDesc = roleDesc;
    }

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }

    @Override
    public String toString() {
        return "Role{" +
                "id=" + id +
                ", roleName='" + roleName + '\'' +
                ", roleDesc='" + roleDesc + '\'' +
                '}';
    }
}

RoleDao.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.RoleDao">
    <resultMap id="roleMap" type="role">
        <id column="rid" property="id"/>
        <result column="role_name" property="roleName"/>
        <result column="role_desc" property="roleDesc"/>
        <collection property="users" ofType="user">
            <id column="id" property="id"/>
            <result column="username" property="username"/>
            <result column="birthday" property="birthday"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
        </collection>
    </resultMap>
    <select id="findAll" resultMap="roleMap">
        <!--角色有分配给用户,这个角色才有用户信息-->
        select u.*,r.id rid,r.role_name,r.role_desc from role r left outer join user_role ur on r.id=ur.rid left outer join user u on ur.uid=u.id
    </select>
</mapper>

相反查询用户所担任的角色

SELECT * FROM USER u LEFT OUTER JOIN  user_role ur ON u.id=ur.uid

在这里插入图片描述

SELECT u.*,r.id roleid,r.role_name,r.role_desc,ur.* FROM USER u LEFT OUTER JOIN  user_role ur ON u.id=ur.uid LEFT OUTER JOIN role r ON r.id = ur.rid

在这里插入图片描述

JNDI

可以成功运行,但是报错:… is not bound in this context…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值