美文网首页
SSM框架mybatis深入了解(二)

SSM框架mybatis深入了解(二)

作者: Seapp | 来源:发表于2020-07-28 12:18 被阅读0次

    一、mybatis中的连接池及事务控制

    1.mybatis中的连接池使用及分析

    • 1.1 连接池简介
      连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。
      连接池就是用于存储连接的容器。该容器是一个集合对象,集合对象必须是线程安全的,不能两个线程拿到同一个连接对象。
      容器必须实现队列的特性:先进先出。
    • 1.2 mybatis中的连接池
     <!-- 配置环境   -->
        <environments default="mysql">
            <!--配置mysql环境-->
            <environment id="mysql">
                <!--配置事务类型 -->
                <transactionManager type="JDBC"></transactionManager>
                <!--配置数据源(连接池)
                    type:配置连接池
                        取值:
                            POOLED:采用传统的javax.sql.DataSource规范中的连接池,在mybatis中有针对该规范的实现。
                            UNPOOLED:采用传统的连接方式,虽然实现了javax.sql.DataSource规范,但并没有池的思想。
                            JNDI:采用服务器提供的JNDI技术实现,来获取DataSource对象,不同服务器所能拿到的DataSource是
                                不同的,注意,如果不是web或maven的war工程,是不能使用的。
                -->
                <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>
            </environment>
        </environments>
    

    2. mybatis中的事务控制使用及分析

    事务是由一组操作组成的一个工作单元。
    事务的四个特性:

    • 原子性(ctomicity)
    • 一致性(consistency)
    • 隔离性(isolation)
    • 持久性(durability)

    二、mybatis基于XML配置的动态SQL语句的实现

      1. <if>标签
      1. <where>标签
      1. <foreach>标签
      1. <sql>代码块
       <!--抽取代码块    -->
        <sql id="defaultSql">
            select * from
        </sql>
        
        <select id="findUserByIds" resultMap="com.seapp.domain.User" parameterType="com.seapp.domain.QueryVo">
    --      抽取代码块的引入   
            <include refid="defaultSql"></include>
    --      where的使用   
            <where>
    --          if的使用
                <if test="ids != null and ids.size >0">
    --              foreach的使用
                    <foreach collection="ids" open="and in (" close=")" item="id" separator=",">
                        #{id}
                    </foreach>
                </if>
            </where>
        </select>
    
    

    三、mybatis中的多表操作

    基于如下示例实现对mybatais多表操作的学习

    示例:用户和账户
    • 一个用户可以有多个账户
    • 一个账户只能属于一个用户(多个账户也可以属于一个用户)
    CREATE TABLE account (
        `ID` INT (11) NOT NULL COMMENT '编号',
        `UID` INT (11) DEFAULT NULL COMMENT '用户编号',
        `MONEY` DOUBLE DEFAULT NULL COMMENT '金额',
        PRIMARY KEY (`ID`),
        KEY `FK_Reference` (`UID`),
     CONSTRAINT `FK_Reference` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
    ) ENGINE = INNODB DEFAULT CHARSET = utf8;
    
    操作步骤:
    • 1.建立两张表:用户表、账户表,让用户表和账户表之间拥有一对多的关系。
    • 2.建立两个实体类:用户实体类、账户实体类,用户实体类与账户实体类之间体现出一对多的关系。
    package com.seapp.domain;
    
    import java.util.Date;
    import java.util.List;
    
    /**
     * @author seapp
     * @date 2020/7/25 22:09
     */
    public class User {
    
        private Integer id;
        private String username;
        private Date birthday;
        private String sex;
        private String address;
    
        //在user实体类中设定与account实体类之间一对多的关系
        private List<Account> accounts;
    
        public List<Account> getAccounts() {
            return accounts;
        }
    
        public void setAccounts(List<Account> accounts) {
            this.accounts = accounts;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer 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 + '\'' +
                    ", accounts=" + accounts +
                    '}';
        }
    }
    
    package com.seapp.domain;
    
    import java.io.Serializable;
    
    /**
     * @author seapp
     * @date 2020/7/28 10:10
     */
    public class Account implements Serializable {
    
        private Integer aId;
        private Integer uid;
        private Double money;
    
        private User user;
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    
        public Integer getaId() {
            return aId;
        }
    
        public void setaId(Integer aId) {
            this.aId = aId;
        }
    
        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;
        }
    
        @Override
        public String toString() {
            return "Account{" +
                    "aId=" + aId +
                    ", uid=" + uid +
                    ", money=" + money +
                    ", user=" + user +
                    '}';
        }
    }
    
    
      1. 建立对应的配置文件。
      1. 实现配置:
        当我们查询用户时,可以同时得到用户下所包含的账户信息。
        当我们查询账户时,可以同时得到账户所属用户信息。

    1. 一对一

    • IAccountDao接口实现:
    package com.seapp.dao;
    
    import com.seapp.domain.Account;
    
    import java.util.List;
    
    /**
     * @author seapp
     * @date 2020/7/28 10:15
     */
    public interface IAccountDao {
        
        /**
         * 查询所有账户,且关联到所属用户
         * @return
         */
        List<Account> findAllAccountUser();
    
    }
    
    
    • map实现
     <!--实体类名与数据库列名不一致时通过resultMap来实现实体类名与列名的对应关系    -->
        <resultMap id="accountUserMap" type="account">
            <id column="aid" property="aId"/>
            <result column="uid" property="uid"/>
            <result column="money" property="money"/>
            <!--asssociation属性来确定一对一实体类,
                column:由哪个字段类确定        -->
            <association property="user" column="uid">
                <id column="id" property="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="findAllAccountUser" resultMap="accountUserMap">
            select a.id AS aid,a.uid,a.money ,u.* 
            from account a ,user u
            where a.uid = u.id;
        </select>
    

    2. 一对多

    • IUserDao接口类实现
    package com.seapp.dao;
    
    import com.seapp.domain.QueryVo;
    import com.seapp.domain.User;
    
    import java.util.List;
    
    /**
     * @author seapp
     * @date 2020/7/25 22:11
     */
    public interface IUserDao {
    
        /**
         * 查询所有,且包含用户对应的账户
         * @return
         */
        List<User> findAll();
    
    
    }
    
    
    • IUserDao.xml map的实现
     <resultMap id="userMap" type="user">
            <id property="id" column="id"></id>
            <result property="username" column="username"/>
            <result property="birthday" column="birthday"/>
            <result property="sex" column="sex"/>
            <result property="address" column="address"/>
            <!-- 指定关联对象accounts集合的映射
                    ofType:指定集合中元素的类型 -->
            <collection property="accounts" ofType="account">
                <id property="aId" column="aid"></id>
                <result property="uid" column="uid"></result>
                <result property="money" column="money"></result>
            </collection>
    
    
        </resultMap>
    
        <!--查询所有-->
        <select id="findAll" resultMap="userMap">
            SELECT
                u.*, a.id AS aid,
                a.uid,
                a.money
            FROM
                USER u
            LEFT OUTER JOIN account a ON a.uid = u.id;
        </select>
    

    3. 多对多

    • 1.建立两张表:用户表、角色表,让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含各自的主键,在中间表中是外键。
    • 2.建立两个实体类:用户实体类、角色实体类,用户实体类与账户实体类之间体现出多对多的关系。各自包含对方一个集合引用
      1. 建立对应的配置文件。
      1. 实现配置:
        当我们查询用户时,可以同时得到用户包含的角色信息。
        当我们查询账户时,可以同时得到所赋予的用户信息。
    //角色表
    CREATE TABLE role (
        `ID` INT (11) NOT NULL COMMENT '编号',
        `ROLE_NAME` VARCHAR (30) DEFAULT NULL COMMENT '角色名称',
        `ROLE_DESC` VARCHAR (30) DEFAULT NULL COMMENT '角色描述',
        PRIMARY KEY (`ID`)
    ) ENGINE = INNODB DEFAULT CHARSET = utf8;
    
    //用户、角色中间表
    CREATE TABLE `user_role` (
        `UID` INT (11) NOT NULL COMMENT '用户编号',
        `RID` INT (11) NOT NULL COMMENT '角色编号',
        PRIMARY KEY (`UID`, `RID`),
        KEY `FK_Reference_role` (`RID`),
        CONSTRAINT `FK_Reference_role` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`),
        CONSTRAINT `FK_Reference_user` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
    ) ENGINE = INNODB DEFAULT CHARSET = utf8;
    
    
    • Role实体类实现:
    package com.seapp.domain;
    
    import java.io.Serializable;
    import java.util.List;
    
    /**
     * @author seapp
     * @date 2020/7/28 11:24
     */
    public class Role implements Serializable {
    
        private Integer id;
        private String roleName;
        private String roleDesc;
    
        private List<User> users;
    
        public List<User> getUsers() {
            return users;
        }
    
        public void setUsers(List<User> users) {
            this.users = 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;
        }
    
        @Override
        public String toString() {
            return "Role{" +
                    "id=" + id +
                    ", roleName='" + roleName + '\'' +
                    ", roleDesc='" + roleDesc + '\'' +
                    ", users=" + users +
                    '}';
        }
    }
    
    
    • IRoleDao.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="com.seapp.dao.IRoleDao">
    
        <resultMap id="roleMap" type="role">
            <id property="id" column="id"/>
            <result property="roleName" column="role_name"/>
            <result property="roleDesc" column="role_desc"/>
            <collection property="users" ofType="user" >
                <id column="userId" property="id" />
                <result property="username" column="username"/>
                <result property="birthday" column="birthday"/>
                <result property="sex" column="sex"/>
                <result property="address" column="address"/>
            </collection>
        </resultMap>
    
    
        <!--查询所有-->
        <select id="findAllRole" resultMap="roleMap">
           SELECT
                r.*, u.id AS userId,
                u.username,
                u.birthday,
                u.sex,
                u.address
            FROM
                role r
            LEFT OUTER JOIN user_role ru ON r.id = ru.rid
            LEFT OUTER JOIN USER u ON ru.uid = u.id;
        </select>
    </mapper>
    
    • IUserDao.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="com.seapp.dao.IUserDao">
        
    
        <resultMap id="userRoleMap" type="user">
            <id property="id" column="id"></id>
            <result property="username" column="username"/>
            <result property="birthday" column="birthday"/>
            <result property="sex" column="sex"/>
            <result property="address" column="address"/>
            <!--指定关联的角色集合信息-->
            <collection property="roles" ofType="role">
                <id property="id" column="roleId"/>
                <result property="roleName" column="role_name"/>
                <result property="roleDesc" column="role_desc"/>
            </collection>
        </resultMap>
        
        <select id="findAllUserRole" resultMap="userRoleMap">
            SELECT
                u.*,r.ID AS roleId,r.ROLE_DESC,r.ROLE_NAME
            FROM
                USER u
            LEFT OUTER JOIN user_role ru ON u.id = ru.rid
            LEFT OUTER JOIN role r ON ru.uid = r.id;
        </select>
    </mapper>
    

    SQL语句与返回结果的封装。

    相关文章

      网友评论

          本文标题:SSM框架mybatis深入了解(二)

          本文链接:https://www.haomeiwen.com/subject/jbcglktx.html