MyBatis的深入和多表

1. MyBatis 的连接池

1.1 MyBatis 的连接池的配置

通过配置文件 SqlMapConfig.xml 中的 dataSource 标签来实现 MyBatis 的连接池的配置

<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>

1.2 MyBatis 连接池的分类

dataSource 标签中的 type 属性表示采用何种连接池方式,type 属性有三种取值:

  1. POOLED:采用传统的 javax.sql.DataSource 规范中的连接池,mybatis 中有针对规范的实现
  2. UNPOOLED:采用传统的获取连接的方式,虽然也实现 Javax.sql.DataSource 接口,但是并没有使用池的思想。
  3. JNDI:采用服务器提供的 JNDI 技术实现,来获取 DataSource 对象,不同的服务器所能拿到 DataSource 是不一样。

注意:在这三种连接池方式中,我们一般采用的是 POOLED 方式

2. MyBatis 的事务控制

2.1 MyBatis 的事务提交方式

观察 Connection 的整个变化过程可以得知,MyBatis 会把 setAutoCommit() 设置为 false,所以我们需要通过 sqlSession.commit() 方法来实现手动提交,才能实现事务控制

@After
public void destory() throws IOException {
    sqlSession.commit();
    // 7.释放资源
    sqlSession.close();
    in.close();
}

2.2 MyBatis 自动提交事务的设置

如果我们想把事务设置为自动提交,可以在创建 SqlSession 对象时,设置自动提交事务为 true

// 创建 SqlSession 对象
session = factory.openSession(true);

注意:在实际开发中,设置为自动提交方式为 false 再根据情况决定是否进行提交,这种方式更常用

3. Mybatis 的动态 SQL 语句

3.1 if 标签

  1. 需求

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

  2. 持久层 Dao 接口

    /**
     *  根据用户信息,查询用户列表
     * @param user
     * @return
     */
    List<User> findByUser(User user);
    
  3. 持久层 Dao 映射配置

    <!--根据用户信息,查询用户列表-->
    <select id="findByUser" parameterType="user" resultType="user">
        select * from user where 1 = 1
        <if test="username != null">
            and username like #{username}
        </if>
        <if test="birthday != null">
            and birthday like #{birthday}
        </if>
        <if test="sex != null">
            and sex like #{sex}
        </if>
        <if test="address != null">
            and address like #{address}
        </if>
    </select>
    
  4. 测试类

    @Test
    public void testFindByUser(){
        User user = new User();
        user.setUsername("%王%");
        user.setSex("%男%");
        List<User> users = mapper.findByUser(user);
        for (User user1 : users) {
            System.out.println(user1);
        }
    }
    

3.2 where 标签

  1. 需求

    为了简化上面 where 1=1 的条件拼装,我们可以采用 where 标签来简化开发。

  2. 持久层 Dao 映射配置

    <!--根据用户信息,查询用户列表-->
    <select id="findByUser" parameterType="user" resultType="user">
        select * from user
        <where>
            <if test="username != null">
                and username like #{username}
            </if>
            <if test="birthday != null">
                and birthday like #{birthday}
            </if>
            <if test="sex != null">
                and sex like #{sex}
            </if>
            <if test="address != null">
                and address like #{address}
            </if>
        </where>
    </select>
    

3.3 foreach 标签

  1. 需求

    传入多个 id 查询用户信息,需要用以下的 sql 语句实现

    select * from user where id in (42,46,52)
    

    这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。

  2. 在 QueryVo 中加入一个 List 集合用于封装参数

    public class QueryVo implements Serializable {
        private User user;
        
        private List<Integer> ids;
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    
        public List<Integer> getIds() {
            return ids;
        }
    
        public void setIds(List<Integer> ids) {
            this.ids = ids;
        }
    }
    
    
  3. 持久层 Dao 接口

    /**
     * 根据 id 集合查询用户
     * @param queryVo
     * @return
     */
    List<User> findByQueryVo(QueryVo queryVo);
    
  4. 持久层 Dao 映射配置

    <!--根据 id 集合查询用户-->
    <select id="findByQueryVo" parameterType="queryVo" resultType="user">
        select * from user
        <where>
            <if test="ids != null and ids.size() > 0">
                <foreach collection="ids" open="id in ( " close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>
    

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

    • collection:代表要遍历的集合元素
    • open:代表语句的开始部分
    • close:代表结束部分
    • item:代表遍历集合的每个元素,生成的变量名
    • sperator:代表分隔符
  5. 测试类

    @Test
    public void testFindByQueryVo(){
        QueryVo queryVo = new QueryVo();
        ArrayList<Integer> ids = new ArrayList<Integer>();
        ids.add(42);
        ids.add(46);
        ids.add(52);
        queryVo.setIds(ids);
        List<User> users = mapper.findByQueryVo(queryVo);
        for (User user : users) {
            System.out.println(user);
        }
    }
    
    

3.4 简化 SQL 片段

  1. 需求

    可将重复的 sql 提取出来,使用时用 include 引用即可,实现 sql 重用的目的。

  2. 定义代码片段

    <!--抽取重复语句代码片段-->
    <sql id="defaultSql">
        select * from user
    </sql>
    

    注意:抽取的代码片段如果还要用来拼接,最后不要加分号

  3. 引用代码片段

    <!--配置查询所有用户-->
    <select id="findAll" resultType="user">
        <include refid="defaultSql"></include>
    </select>
    

4. Mybatis 多表查询

4.1 表之间的几种关系

  1. 表之间的几种关系

    1. 一对一
    2. 一对多
    3. 多对一
    4. 多对多
  2. 举例

    1. 人和身份证号的关系就是一对一(一个人只能有一个身份证号,一个身份证号只能属于一个人)
    2. 用户和订单就是一对多(一个用户可以下多个订单)
    3. 订单和用户就是多对一(多个订单属于同一个用户)
    4. 老师和学生之间就是多对多(一个学生可以被多个老师教过,一个老师可以交多个学生)
  3. 注意

    在多对一的关系中,因为拿出每一个订单,它都只能属于一个用户,所以 Mybatis 就把多对一看成了一对一

4.2 一对一,一对多关系实例

  1. 需求

    实现用户和账户的关系,一个用户可以有多个账户,一个账户只能有一个用户

  2. 步骤

    1. 建立两张表,用户表和账户表
    2. 建立两个实体类,用户实体类和账户实体类
    3. 建立两个持久层 Dao 接口,用户 Dao 和账户 Dao
    4. 建立两个配置文件,用户配置文件和账户配置文件
    5. 建立 SqlMapConfig.xml 配置文件
    6. 建立测试类
    7. 增加功能:查询所有账户,同时包含用户名和地址信息(一对一)
    8. 增加功能:查询所有用户,同时包含用户下的所有账户信息(一对多)
  3. 实现

    1. 建立两张表

      用户表

      DROP TABLE IF EXISTS `user`;
      CREATE TABLE `user` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `username` varchar(32) NOT NULL COMMENT '用户名称',
        `birthday` datetime DEFAULT NULL COMMENT '生日',
        `sex` char(1) DEFAULT NULL COMMENT '性别',
        `address` varchar(256) DEFAULT NULL COMMENT '地址',
        PRIMARY KEY (`id`)
      ) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8;
      
      

      账户表

      DROP TABLE IF EXISTS `account`;
      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_8` (`UID`),
        CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      
    2. 建立两个实体类

      用户实体类

      public class User implements Serializable {
          private Integer id;
          private String username;
          private Date birthday;
          private String sex;
          private String address;
      
          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 + '\'' +
                      '}';
          }
      }
      
      

      账户实体类

      public class Account {
          private Integer id;
          private Integer uid;
          private Double money;
      
          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;
          }
      
          @Override
          public String toString() {
              return "Account{" +
                      "id=" + id +
                      ", uid=" + uid +
                      ", money=" + money +
                      '}';
          }
      }
      
      
    3. 建立两个持久层 Dao 接口

      用户 Dao

      /**
       * 用户持久层接口
       */
      public interface UserDao {
          /**
           * 查询所有用户
           * @return
           */
          public List<User> findAll();
      
          /**
           * 查询单个用户
           * @param id
           */
          User findById(Integer id);
      
      }
      

      账户 Dao

      /**
       * 账户持久层接口
       */
      public interface AccountDao {
          /**
           * 查询所有账户
           * @return
           */
          public List<Account> findAll();
      
      }
      
      
    4. 建立两个配置文件

      用户配置文件

      <?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.zt.dao.UserDao">
          
          <!--配置查询所有用户-->
          <select id="findAll" resultType="user">
              select * from user
          </select>
      
          <!--查询单个用户-->
          <select id="findById" parameterType="java.lang.Integer" resultType="com.zt.domain.User">
              select * from user where id=#{id};
          </select>
      </mapper>
      

      账户配置文件

      <?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.zt.dao.AccountDao">
          
          <!--配置查询所有账户-->
          <select id="findAll" resultType="account">
              select * from account
          </select>
      
      </mapper>
      
      
    5. 建立 SqlMapConfig.xml 配置文件

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-config.dtd">
      
      <configuration>
          <properties resource="jdbcConfig.properties"></properties>
          <typeAliases>
              <!--批量别名,用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
              <package name="com.zt.domain"></package>
          </typeAliases>
          <!-- 配置 mybatis 的环境 -->
          <environments default="mysql">
              <!-- 配置 mysql 的环境 -->
              <environment id="mysql">
                  <!-- 配置事务的类型 -->
                  <transactionManager type="JDBC"></transactionManager>
                  <!-- 配置连接数据库的信息:用的是数据源(连接池) -->
                  <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>
      
          <!-- 告知 mybatis 映射配置的位置 -->
          <mappers>
              <package name="com.zt.dao"></package>
          </mappers>
      
      </configuration>
      
    6. 建立测试类

      MybatisTest

      public class MybatisTest {
      
          private InputStream in;
          private SqlSession sqlSession;
          private UserDao mapper;
      
          @Before
          public void init() throws IOException {
              // 1.读取配置文件
              in = Resources.getResourceAsStream("SqlMapConfig.xml");
              // 2.创建 SqlSessionFactory 的构建者对象
              SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
              // 3.使用构建者创建工厂对象 SqlSessionFactory
              SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
              // 4.使用 SqlSessionFactory 生产 SqlSession 对象
              sqlSession = sqlSessionFactory.openSession();
              // 5.使用 SqlSession 创建 dao 接口的代理对象
              mapper = sqlSession.getMapper(UserDao.class);
          }
      
          @After
          public void destory() throws IOException {
              sqlSession.commit();
              // 7.释放资源
              sqlSession.close();
              in.close();
          }
      
          @Test
          public void testFindAll() {
              List<User> all = mapper.findAll();
              for (User user : all) {
                  System.out.println(user);
              }
          }
      
      
          @Test
          public void testFindById(){
              User user = mapper.findById(52);
              System.out.println(user);
          }
      
      }
      
      

      MybatisTest2

      public class MybatisTest2 {
          private InputStream in;
          private SqlSession sqlSession;
          private AccountDao mapper;
      
          @Before
          public void init() throws IOException {
              // 1.读取配置文件
              in = Resources.getResourceAsStream("SqlMapConfig.xml");
              // 2.创建 SqlSessionFactory 的构建者对象
              SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
              // 3.使用构建者创建工厂对象 SqlSessionFactory
              SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
              // 4.使用 SqlSessionFactory 生产 SqlSession 对象
              sqlSession = sqlSessionFactory.openSession();
              // 5.使用 SqlSession 创建 dao 接口的代理对象
              mapper = sqlSession.getMapper(AccountDao.class);
          }
      
          @After
          public void destory() throws IOException {
              sqlSession.commit();
              // 7.释放资源
              sqlSession.close();
              in.close();
          }
      
          @Test
          public void findAll() {
              List<Account> accounts = mapper.findAll();
              for (Account account : accounts) {
                  System.out.println(account);
              }
          }
      }
      
      
    7. 增加功能:查询所有账户,同时包含用户名和地址信息

      1. 修改账户实体类

        public class Account {
            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 +
                        ", user=" + user +
                        '}';
            }
        }
        
        
      2. 修改账户 Dao

        /**
         * 查询所有账户,并带有用户名和地址信息
         * @return
         */
        public List<Account> findAllWithUser();
        
      3. 修改账户配置文件

        <mapper namespace="com.zt.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" 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" resultType="account">
                select * from account
            </select>
        
            <!--配置查询所有账户,并带有用户名和地址信息-->
            <select id="findAllWithUser" resultMap="accountUserMap">
                select a.id as aid, a.uid, a.money, u.*
                from account a, user u
                where u.id = a.uid;
            </select>
        
        </mapper>
        
        
        
      4. 修改测试类

        @Test
        public void testFindAllWithUser() {
            List<Account> allWithUser = mapper.findAllWithUser();
            for (Account account : allWithUser) {
                System.out.println(account);
            }
        }
        
    8. 增加功能:查询所有用户,同时包含用户下的所有账户信息(一对多)

      1. 修改用户实体类

        public class User implements Serializable {
            private Integer id;
            private String username;
            private Date birthday;
            private String sex;
            private String address;
         // 一对多关系映射:主表实体应该包含从表实体的集合引用
            private List<Account> 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;
            }
        
            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 + '\'' +
                        ", accounts=" + accounts +
                        '}';
            }
        }
        
        
      2. 修改用户 Dao

        /**
         * 查询所有用户,同时包含用户下的所有账户信息
         * @return
         */
        public List<User> findAllWithAccount();
        
      3. 修改用户配置文件

        <?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.zt.dao.UserDao">
            <!-- 定义封装 user和 account 的 resultMap -->
            <resultMap id="UserAccountMap" type="user">
             <id property="id" column="id"></id>
                <result property="username" column="username"></result>
             <result property="birthday" column="birthday"></result>
                <result property="sex" column="sex"></result>
                <result property="address" column="address"></result>
                <!-- 配置 user 对象中 accounts 集合的映射 -->
                <collection property="accounts" ofType="account">
                    <id property="id" column="aid"></id>
                    <result property="uid" column="uid"></result>
                    <result property="money" column="money"></result>
                </collection>
            </resultMap>
            
            <!--配置查询所有用户-->
            <select id="findAll" resultType="user">
                select * from user
            </select>
        
            <!--查询单个用户-->
            <select id="findById" parameterType="java.lang.Integer" resultType="com.zt.domain.User">
                select * from user where id=#{id};
            </select>
        
            <!--配置查询所有用户,同时包含用户下的所有账户信息-->
            <select id="findAllWithAccount" resultMap="UserAccountMap">
                select a.id as aid, a.uid, a.money, u.*
                from user u left join account a
                on u.id = a.uid
            </select>
            
        </mapper>
        
        
        
      4. 修改测试类

        @Test
        public void testFindAllWithAccount() {
            List<User> allWithAccount = mapper.findAllWithAccount();
            for (User user : allWithAccount) {
                System.out.println(user);
            }
        }
        

4.3 多对多关系实例

  1. 需求

    实现用户和角色的关系,一个用户可以有多个角色,一个角色可以赋予多个用户

  2. 步骤

    1. 建立三张表,用户表,角色表,中间表(中间表中有两个外键,分别是用户表和角色表的主键)
    2. 建立两个实体类,用户实体类和角色实体类(各自包含对方一个集合引用)
    3. 建立两个持久层 Dao 接口,用户 Dao 和角色 Dao
    4. 建立两个配置文件,用户配置文件和角色配置文件
    5. 建立 SqlMapConfig.xml 配置文件
    6. 建立测试类
    7. 增加功能:查询用户,可以同时得到用户所包含的角色信息(多对多)
    8. 增加功能:查询角色,可以同时得到角色的所赋予的用户信息(多对多)
  3. 实现

    1. 建立三张表

      用户表

      DROP TABLE IF EXISTS `user`;
      CREATE TABLE `user` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `username` varchar(32) NOT NULL COMMENT '用户名称',
        `birthday` datetime DEFAULT NULL COMMENT '生日',
        `sex` char(1) DEFAULT NULL COMMENT '性别',
        `address` varchar(256) DEFAULT NULL COMMENT '地址',
        PRIMARY KEY (`id`)
      ) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8;
      
      

      角色表

      DROP TABLE IF EXISTS `role`;
      CREATE TABLE `role` (
        `ID` int(11) NOT NULL COMMENT '编号',
        `ROLE_NAME` varchar(30) DEFAULT NULL COMMENT '角色名称',
        `ROLE_DESC` varchar(60) DEFAULT NULL COMMENT '角色描述',
        PRIMARY KEY (`ID`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      

      中间表

      DROP TABLE IF EXISTS `user_role`;
      CREATE TABLE `user_role` (
        `UID` int(11) NOT NULL COMMENT '用户编号',
        `RID` int(11) NOT NULL COMMENT '角色编号',
        PRIMARY KEY (`UID`,`RID`),
        KEY `FK_Reference_10` (`RID`),
        CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`),
        CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      
    2. 建立两个实体类

      用户实体类

      public class User implements Serializable {
          private Integer id;
          private String username;
          private Date birthday;
          private String sex;
          private String address;
      
          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 + '\'' +
                      '}';
          }
      }
      
      

      角色实体类

      public class Role implements Serializable {
          private Integer roleId;
          private String roleName;
          private String roleDesc;
      
          public Integer getRoleId() {
              return roleId;
          }
      
          public void setRoleId(Integer roleId) {
              this.roleId = roleId;
          }
      
          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{" +
                      "roleId=" + roleId +
                      ", roleName='" + roleName + '\'' +
                      ", roleDesc='" + roleDesc + '\'' +
                      '}';
          }
      }
      
      
    3. 建立两个持久层 Dao 接口

      用户 Dao

      /**
       * 用户持久层接口
       */
      public interface UserDao {
          /**
           * 查询所有用户
           * @return
           */
          List<User> findAll();
      
          /**
           * 查询单个用户
           * @param id
           */
          User findById(Integer id);
      
      }
      
      

      角色 Dao

      /**
       * 角色持久层接口
       */
      public interface RoleDao {
          /**
           * 查询所有角色
           * @return
           */
          List<Role> findAll();
      }
      
      
    4. 建立两个配置文件

      用户配置文件

      <?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.zt.dao.UserDao">
          
          <!--配置查询所有用户-->
          <select id="findAll" resultType="user">
              select * from user
          </select>
      
          <!--查询单个用户-->
          <select id="findById" parameterType="java.lang.Integer" resultType="com.zt.domain.User">
              select * from user where id=#{id};
          </select>
          
      </mapper>
      
      
      

      角色配置文件

      <?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.zt.dao.RoleDao">
          <resultMap id="roleMap" type="role">
              <id property="roleId" column="id"></id>
              <result property="roleName" column="role_name"></result>
              <result property="roleDesc" column="role_desc"></result>
          </resultMap>
      
          <!--配置查询所有角色-->
          <select id="findAll" resultMap="roleMap">
              select * from role
          </select>
      </mapper>
      
    5. 建立 SqlMapConfig.xml 配置文件

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-config.dtd">
      
      <configuration>
          <properties resource="jdbcConfig.properties"></properties>
          <typeAliases>
              <!--批量别名,用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
              <package name="com.zt.domain"></package>
          </typeAliases>
          <!-- 配置 mybatis 的环境 -->
          <environments default="mysql">
              <!-- 配置 mysql 的环境 -->
              <environment id="mysql">
                  <!-- 配置事务的类型 -->
                  <transactionManager type="JDBC"></transactionManager>
                  <!-- 配置连接数据库的信息:用的是数据源(连接池) -->
                  <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>
      
          <!-- 告知 mybatis 映射配置的位置 -->
          <mappers>
              <package name="com.zt.dao"></package>
          </mappers>
      
      </configuration>
      
    6. 建立测试类

      public class MybatisTest2 {
      
          private InputStream in;
          private SqlSession sqlSession;
          private RoleDao mapper;
      
          @Before
          public void init() throws IOException {
              // 1.读取配置文件
              in = Resources.getResourceAsStream("SqlMapConfig.xml");
              // 2.创建 SqlSessionFactory 的构建者对象
              SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
              // 3.使用构建者创建工厂对象 SqlSessionFactory
              SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
              // 4.使用 SqlSessionFactory 生产 SqlSession 对象
              sqlSession = sqlSessionFactory.openSession();
              // 5.使用 SqlSession 创建 dao 接口的代理对象
              mapper = sqlSession.getMapper(RoleDao.class);
          }
      
          @After
          public void destory() throws IOException {
              sqlSession.commit();
              // 7.释放资源
              sqlSession.close();
              in.close();
          }
      
          @Test
          public void testFindAll() {
              List<Role> all = mapper.findAll();
              for (Role role : all) {
                  System.out.println(role);
              }
          }
      
          
      }
      
      
    7. 增加功能:查询所有用户,可以同时得到用户所包含的角色信息

      1. 修改用户实体类

        public class User implements Serializable {
            private Integer id;
            private String username;
            private Date birthday;
            private String sex;
            private String address;
            // 多对多的关系映射:一个用户可以有多个角色
            private List<Role> roles;
        
            public List<Role> getRoles() {
                return roles;
            }
        
            public void setRoles(List<Role> roles) {
                this.roles = roles;
            }
        
            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 + '\'' +
                        ", roles=" + roles +
                        '}';
            }
        }
        
        
      2. 修改用户 Dao

        /**
         * 查询所有用户,可以同时得到用户所包含的角色信息
         * @return
         */
        List<User> findAllWithRole();
        
      3. 修改用户配置文件

        <?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.zt.dao.UserDao">
            <resultMap id="userMap" type="user">
                <id property="id" column="id"></id>
                <result property="username" column="username"></result>
                <result property="birthday" column="birthday"></result>
                <result property="sex" column="sex"></result>
                <result property="address" column="address"></result>
                <collection property="roles" ofType="role">
                    <id property="roleId" column="rid"></id>
                    <result property="roleName" column="role_name"></result>
                    <result property="roleDesc" column="role_desc"></result>
                </collection>
            </resultMap>
        
            <!--配置查询所有用户-->
            <select id="findAll" resultType="user">
                select * from user
            </select>
        
            <!--查询单个用户-->
            <select id="findById" parameterType="java.lang.Integer" resultType="com.zt.domain.User">
                select * from user where id=#{id};
            </select>
        
            <!--配置查询所有用户,可以同时得到用户所包含的角色信息-->
            <select id="findAllWithRole" resultMap="userMap">
                select u.*, r.id as rid, r.role_name, r.role_desc from user u
                left join user_role ur on u.id = ur.uid
                left join role r on r.id = ur.rid;
            </select>
            
        </mapper>
        
        
        
      4. 修改测试类

        @Test
        public void testFindAllWithRole() {
            List<User> allWithRole = mapper.findAllWithRole();
            for (User user : allWithRole) {
                System.out.println(user);
            }
        }
        
    8. 增加功能:查询所有角色,可以同时得到角色的所赋予的用户信息

      1. 修改角色实体类

        public class Role implements Serializable {
            private Integer roleId;
            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 getRoleId() {
                return roleId;
            }
        
            public void setRoleId(Integer roleId) {
                this.roleId = roleId;
            }
        
            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{" +
                        "roleId=" + roleId +
                        ", roleName='" + roleName + '\'' +
                        ", roleDesc='" + roleDesc + '\'' +
                        '}';
            }
        }
        
        
      2. 修改角色 Dao

        /**
         * 查询所有角色,可以同时得到角色的所赋予的用户信息
         * @return
         */
        List<Role> findAllWithUser();
        
      3. 修改角色配置文件

        <?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.zt.dao.RoleDao">
            <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 property="id" column="id"></id>
                    <result property="username" column="username"></result>
                    <result property="birthday" column="birthday"></result>
                    <result property="sex" column="sex"></result>
                    <result property="address" column="address"></result>
                </collection>
            </resultMap>
        
            <!--配置查询所有角色-->
            <select id="findAll" resultMap="roleMap">
                select * from role
            </select>
            <!--配置查询所有角色,可以同时得到角色的所赋予的用户信息-->
            <select id="findAllWithUser" resultMap="roleMap">
                select r.id as rid, r.role_name, r.role_desc, u.* from role r
                left join user_role ur on r.id = ur.rid
                left join user u on u.id = ur.uid;
            </select>
        </mapper>
        
      4. 修改测试类

        @Test
        public void testFindAllWithUser() {
            List<Role> allWithUser = mapper.findAllWithUser();
            for (Role role : allWithUser) {
                System.out.println(role);
            }
        }
        
发布了64 篇原创文章 · 获赞 20 · 访问量 6498

猜你喜欢

转载自blog.csdn.net/bm1998/article/details/101936474
今日推荐