MyBatis小记_two

目录

一,MyBatis 连接池的配置

事务

二,动态SQL语句

动态SQL语句之if标签

演示if标签

动态SQL语句之foreach标签

foreach标签演示

Set 标签

三,抽取重复的SQL代码片段

四,多表查询

1.实体之间的关系

2.多表查询准备步骤

3.建立两张表一张用户表一张账户表

4.建立两张表对应的实体类

5.提供用户和账户的接口

6.提供用户和账户的映射文件

7.编写核心配置文件

8.我们先单表测试一下查询所有账户

9.当我们单表查询测试没有问题后,我们接下来进行多表查询

10.我们看一下在程序中进行查询,查询该账户所对应的用户信息,该怎么配置和编写

11. 接下来,再账户的接口中提供相应的方法

12.在账户的映射文件中编写多表查询的配置

13.测试

14.说明:采用这种继承的方式进行多表查询不常用,仅作了解

使用开发中常用的方式进行多表查询

1.首先我们在多表对应的实体类中,维护一个单表一方的实体类对象

2.在多表实体类的 IAccountDao.xml 映射文件中,进行一对一关系的配置

多表查询之一对多的查询,也就是一个用户可以有很多个账户

1.我在单表实体类中提供一个集合来描述这个一对多的关系,集合里面装的就是多个账户

2.在单表实体类的 IUserDao.xml 映射文件中,进行配置

3.编写sql语句,查询所有用户对应的账户信息,如果该用户没有账户信息以null展示

4. 修改查询所有用户的配置,把返回类型修改为我们配置的映射关系,以及把sql语句粘贴过来

5.测试

多表查询之多对多

1.多对多的处理

2.建立两张表:用户表,角色表

3.建立用户和角色的实体类

4.提供用户和角色的接口

5.提供接口对应的映射文件

6.核心配置文件还是之前的,就不用动了

7.下来,我们查询所有角色有哪些用户在使用

8.sql 语句编写好后,我们在实体类中来体现多对多的关系

9.在角色的接口中提供方法

10.在角色接口的 IRoleDao.xml 映射文件中进行配置

11.把配置查询的返回类型,以及sql语句

12.测试

下来就是查询该用户有哪些角色

1.在用户的接口中提供方法

2.在用户的实体类中,维护一个集合,用来描述多对多的关系

3.修改SQL语句

4.在IUserDao.xml 映射文件中编写配置

5.测试


一,MyBatis 连接池的配置

连接池:相当于一个容器,会提前初始化一定数量的连接对象,以便重复使用
1、我们在实际开发中都会使用连接池。因为它可以减少我们获取连接所消耗的时间。
 mybatis中的连接池
 mybatis连接池提供了3种方式的配置:
    配置的位置:
    主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。
type属性的取值:
    POOLED   采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现
    UNPOOLED 采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。
​

事务

mybatis中的事务
    什么是事务(很多步骤,是一个整体不可再分割,组成事务的每一个步骤,要么同时成功,要么同时失败)
    事务的四大特性ACID
    不考虑隔离性会产生的3个问题
    解决办法:四种隔离级别  
​
mybatis中的事务 
它是通过sqlsession对象的commit方法和rollback方法实现事务的提交和回滚
如果我们不想手动提交事务,可以在创建SqlSession对象时传入true,表示自动提交事务
 SqlSession session = factory.openSession(true); 

二,动态SQL语句

Mybatis 的动态 SQL 语句 
Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,
有些时候业务逻辑复杂时,我们的 SQL 是动态变 化的,
此时在前面的学习中我们的 SQL 就不能满足要求了

动态SQL语句之if标签

我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。
比如在 id 如果不为空时可以根据 id 查询, 
如果 username 不同空时还要加入用户名作为条件。
这种情况在我们的多条件组合查询中经常会碰到。
​
 
​
注意:标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法。 
另外要注意 where 1=1 的作用~

演示if标签

1.在接口中提供一个方法,根据性别和年龄去查询用户
 public interface IUserDao {
    //根据姓名和性别去查询用户
    List selectUserByNameAndSex(User user);
}
​
2.在映射文件中进行配置
  
  
    
    
    说明:标签的 test 属性中写的是对象的属性名
    
 3.测试 :
 @Test
    public void testLikeByVO() {
        IUserDao dao = sqlSession.getMapper(IUserDao.class);
        User user = new User();
        user.setUsername("沈某某");
       user.setSex("男");
        List list = dao.selectUserByNameAndSex(user);
​
        for (User user1 : list) {
​
            System.out.println(user1);
        }
    }
    
4:问题:就是单纯用if标签来拼接条件,我们在写条件的时候,得把 where 1=1 写上 麻烦
那能不能 不写where 和 1=1 呢? 可以 那就得使用一个标签叫where标签
​
5.所以我们可以写成下面这样
​
  
    
        select * from user
        
            
                #{uid}
            
        
     
     
 foreach标签中的属性说明: 
 collection:代表要遍历的集合元素,注意编写时不要写#{}  
open:代表语句的开始部分 
 close:代表结束部分
 item:当前遍历的集合中的元素
 separator:分隔符
 
 4.测试:
     @Test
    public void testUerByIDS() {
        IUserDao dao = sqlSession.getMapper(IUserDao.class);
        List list = Arrays.asList(50, 51, 52);
        QueryVO queryVO = new QueryVO();
        queryVO.setList(list);
        List users = dao.selectUserByIDS(queryVO);
        for (User user : users) {
            System.out.println(user);
        }
    }
    
  5.当然严谨期间你可以在遍历集合的时候,使用if标签对集合进行判断,当集合长度大于0并且集合不为空再去遍历集合
  
     
    

Set 标签


    UPDATE t_user 
    
        
            name = #{name},
        
        
            age = #{age},
        
    
    
        
            AND id = #{id}
        
    

我们将sql中的set去掉了,加了个set元素,set元素会内部嵌套的sql进行处理,将这部分sql前后的逗号给去掉并在前面加上set

当预期id和age的时候,生成的sql:

UPDATE t_user SET age = ? where id = ?

三,抽取重复的SQL代码片段

1.我们在映射文件中编写增删改查的配置时,写的一些SQL语句有一些片段是重复的 比如 select * from user
那么我们可以把这些重复的sql代码抽取处理,就可以 复用
​
2. 我们在映射文件中可以使用一个sql标签来抽象重复的sql代码
​
 
    
        select * from user  
    
​
​
3.在其他地方,有使用到select * from user 这条语句的地方,就可以通过id来引用,引用要使用一个标签
  
    
        在比如下面也可以引用sql代码片段
       
    

四,多表查询

1.实体之间的关系

表之间的关系有几种:一对多,多对一 ,一对一,多对多
    举例:
        用户和订单就是一对多
        订单和用户就是多对一
            一个用户可以下多个订单
            多个订单属于同一个用户
        人和身份证号就是一对一
            一个人只能有一个身份证号
            一个身份证号只能属于一个人
​
        老师和学生之间就是多对多
            一个学生可以被多个老师教过
            一个老师可以交多个学生
    特例:
        用户和订单就是一对多
        如果拿出每一个订单,他都只能属于一个用户。
        所以Mybatis就把多对一看成了一对一。
    

2.多表查询准备步骤

示例:用户和账户
            一个用户可以有多个账户
            一个账户只能属于一个用户(多个账户也可以属于同一个用户)
        步骤:
            1、建立两张表:用户表,账户表
                让用户表和账户表之间具备一对多的关系:需要使用外键在账户表中添加
            2、建立两个实体类:用户实体类和账户实体类
                让用户和账户的实体类能体现出来一对多的关系
            3、建立两个配置文件
                用户的配置文件
                账户的配置文件
            4、实现配置:
                当我们查询用户时,可以同时得到用户下所包含的账户信息
                当我们查询账户时,可以同时得到账户的所属用户信息
​

3.建立两张表一张用户表一张账户表

用户表我们在第一天的时候,已经建立好,账户表,那第一天的资料中有
那么用户表和账户表之间是一对用的关系,且添加了外键约束

4.建立两张表对应的实体类

public class User implements Serializable {
 
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
     //get set 方法略 自己补上
}
​
public class Account implements Serializable {
    private Integer id;
    private Integer uid;
    private Double money;
    //get set 方法略 自己补上
 }
​
注意:实体类的属性名和表的字段名保持一致

5.提供用户和账户的接口

//提供用户的接口,把我们前的操作保留两个
public interface IUserDao {
    //查询所有用户
    List findAll();
    //根据id查询一个用户
    User selectUserById(Integer id);
}
​
​
//提供账户的接口
public interface IAccountDao {
    //等会再添加增删改查的操作的方法
}
​

6.提供用户和账户的映射文件

//用户的映射文件

    
    
    
    

​
​
//账户的映射文件 
​

   

​
注意:映射文件所在的文件夹层次结构,要和接口的包名保持一致,映射文件名和接口名保持一致
​
​

7.编写核心配置文件

注意:核心配置文件,引入dao接口的映射文件采用扫描对应包下的所有接口
​



    
    
    
    
        
        
    
    
        
            
            
                
                
                
                
            
        
    
    
    
        
        
    

8.我们先单表测试一下查询所有账户

1.我们在账户的接口中提供查询所有账户信息的方法
​
    public interface IAccountDao {
     List findAll();
    }
    
2. 编写账户的映射文件
   

    

​
3.测试:单独写一个测试Account的测试类,使用@Before @After 注解来加载配置文件和释放资源
  
  @Test
    public void testFindAll(){
        IAccountDao dao = sqlSession.getMapper(IAccountDao.class);
        List list = dao.findAll();
        for (Account account : list) {
            System.out.println(account);
        }
    }
​

9.当我们单表查询测试没有问题后,我们接下来进行多表查询

1.我们要查询 所有账户所对应的用户信息
 我们先在小海豚中编写sql语句测试一下
 SELECT a.*,u.* FROM account a,USER u WHERE a.`UID`=u.`id`;
 通过上面的查询语句就可以查询出账户所属的用户信息 
 但是 账户表里有个字段叫 id  用户表里有个字段叫id  重名了,那我们可以给账户表里的id字段起个别名
 或者我们不展示用户表里的id字段 也可以
 可以写成下面的
SELECT a.*,u.`username`,u.`address` FROM account a,USER u WHERE a.`UID`=u.`id`;
 
也就是 用户表中,我只展示了姓名和地址两个字段,说明问题就行了 
 

10.我们看一下在程序中进行查询,查询该账户所对应的用户信息,该怎么配置和编写

1.因为我们多表查询出的数据既有账户信息还有用户信息,那么得将所有信息封装到一个实体类中,那账户的实体类
中没有用户的信息的字段,所以我们提供一个实体类,继承账户的实体,然后在子类里面,提供封装用户信息的字段
​
public class AccountUser extends Account{
    //我提供了两个字段,因为我们等会查询的时候,只查询user表的两个字段,当然你要查几个字段,你就在实体类中提供几个字段,我提供两个说明问题就行了
    private String username;
    private String address;
    //get set 方法略,自己补上
    
    //这里提供toString()方法,里面再调用一下父类的toString()方法,等会测试打印的时候,可以看到所有字段的信息
    @Override
    public String toString() {
        //调用一下父类的toString()
        return super.toString()+"  AccountUser{" +
                "username='" + username + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
​

11. 接下来,再账户的接口中提供相应的方法

public interface IAccountDao {
    //查询所有账户信息
    List findAll();
    //查询该账户所对应的用户信息 注意范型,是Account的子类,因为他里面的属性,加上从父类继承下来属性,就能封装下我们查询出来的数据
    List findAccountAndUser();
}

12.在账户的映射文件中编写多表查询的配置

 
    
 注意:返回类型是Account的子类,还有sql语句的编写   

13.测试

 @Test
    public void testFindAccountAndUser() {
        IAccountDao dao = sqlSession.getMapper(IAccountDao.class);
        List list = dao.findAccountAndUser();
        for (AccountUser account : list) {
            System.out.println(account);
        }
    }
    
    

14.说明:采用这种继承的方式进行多表查询不常用,仅作了解

使用开发中常用的方式进行多表查询

1.采用继承的方式,不推荐使用。那么我们怎么能体现出这种一对一的关系呢?
​
2.我们在实体类中来体现这种一对一的关系
  

1.首先我们在多表对应的实体类中,维护一个单表一方的实体类对象

public class Account implements Serializable {
    private Integer id;
    private Integer uid;
    private Double money;
    //在多表实体类中,维护单表实体类的对象
    private User user;
    
    //get set 方法省略 自己补上
    
}    

2.在多表实体类的 IAccountDao.xml 映射文件中,进行一对一关系的配置

1.在配置之前,我们现在小海豚中编写sql语句测试一下 
  那么这次我们可以把 用户表的所有字段都展示完,账户表中的一个id字段名和用户表中的id字段名一样,
  我们给账户表中的id字段起个别名,sql语句如下:
  
  SELECT a.id AS aid,a.uid,a.money,u.* FROM account a,USER u WHERE a.`UID`=u.`id`;
  
  我们在映射文件中 就可以使用上面这条sql语句
  
2.接下来在多表实体类的映射文件中进行一对一映射关系的配置
   * 先使用resultMap表签 配置多表和实体类的映射关系
  *  然后使用association这个标签来配置一对一
​
   
    
        
        
        
        
        
        
        
            
            
            
            
            
            
        
​
    
  
 3.  修改查询所有账户的配置的返回值类型,修改为我们配置的映射关系   resultMap="myAccountMap"
 
  
    
 4.修改sql语句
 
 
 5.测试:通过account.getUser();可以查看该账户对应的用户信息
 
    @Test
    public void testFindAll(){
        IAccountDao dao = sqlSession.getMapper(IAccountDao.class);
        List list = dao.findAll();
        for (Account account : list) {
            System.out.println(account);
            //获取该账户对应的用户信息
            User user = account.getUser();
            System.out.println(user);
        }
    }
   
   

多表查询之一对多的查询,也就是一个用户可以有很多个账户

1.我在单表实体类中提供一个集合来描述这个一对多的关系,集合里面装的就是多个账户

public class User implements Serializable {
 
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    /*在单表实体类中提供集合,来描述一对多的关系*/
    private List accounts;
    
     //get set 方法略 自己补上
     
  }   

2.在单表实体类的 IUserDao.xml 映射文件中,进行配置

* 使用resultMap标签 配置实体类和表的映射关系
* 使用collection标签 配置集合 
    collection标签 有两个属性 
        1. property   主表实体类中维护的那个集合
        2. ofType     集合中装的什么类型
​
​

        
        
        
        
        
        
​
        
        
            
            
            
            
            
        
    

3.编写sql语句,查询所有用户对应的账户信息,如果该用户没有账户信息以null展示

在小海豚中编写sql语句测试好
​
-- 我要查询所有用户的账户信息,没有账户信息的以null展示,但是所有用户信息必须展示出来,
-- 内连接不行,因为内连接不符合条件的是不展示
-- 所以我们使用外连接
SELECT u.*,a.id AS aid,a.`MONEY`,a.`UID` FROM USER u LEFT OUTER JOIN account a ON u.`id`=a.`UID`;

4. 修改查询所有用户的配置,把返回类型修改为我们配置的映射关系,以及把sql语句粘贴过来

修改返回值类型 改为  resultMap="userMap"
​

    

5.测试

     @Test
    public void testFindAll() throws IOException {
        //获取接口的代理对象
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        //执行查询操作
        List list = userDao.findAll();
        for (User user : list) {
            System.out.println(user);
            //获取该用户对应的账户信息
            List accounts = user.getAccounts();
            System.out.println(accounts);
        }
    }

多表查询之多对多

1.多对多的处理

    多对多的处理
    示例:用户和角色
            一个用户可以有多个角色 
            一个角色可以赋予多个用户
    步骤:
        1、建立两张表:用户表,角色表
        让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含各自的主键,在中间表中是外键。
        2、建立两个实体类:用户实体类和角色实体类
            让用户和角色的实体类能体现出来多对多的关系
            各自包含对方一个集合引用
        3、建立两个配置文件
            用户的配置文件
            角色的配置文件
        4、实现配置:
            当我们查询用户时,可以同时得到用户所包含的角色信息
            当我们查询角色时,可以同时得到角色的所赋予的用户信息  

2.建立两张表:用户表,角色表

因为用户和角色是多对多的关系,所以还需要建立一张中间表
建表语句,在第一天的资料中有,这里就省略了

3.建立用户和角色的实体类

 //用户的实体类
public class User implements Serializable {
 
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    //get set 方法略 自己补上
}  
​
​
//角色的实体类
public class Role implements Serializable {
    private Integer id;
    private String roleName;
    private String roleDesc;
    //get set 方法略 自己补上
}
​
注意:这里我故意没让角色实体类的属性名和表中的字段名保持一致,也就是提醒我们要配置映射

4.提供用户和角色的接口

public interface IUserDao {
    //查询所有用户
    List findAll();
}
​
public interface IRoleDao {
    //查询所有角色对应的用户信息
    List findAll();
}
​

5.提供接口对应的映射文件




    //里面等会再来编写

6.核心配置文件还是之前的,就不用动了

7.下来,我们查询所有角色有哪些用户在使用

1.我们现在小海豚中,把sql语句先测试好
 我们一步一步来编写sql语句 
 * 先查把角色表和中间表关联起来查询
 SELECT r.*,ur.* FROM role r LEFT OUTER JOIN user_role ur ON r.`id`=ur.`RID`;
 
 * 接着,上一步查询的数据里面还没有 用户的信息,所以再继续加入 user表查询
 SELECT r.*,u.* FROM role r LEFT OUTER JOIN user_role ur ON r.`id`=ur.`RID` LEFT OUTER JOIN USER u ON u.`id`=ur.`UID`
 注意:中间表的字段信息,不用,所以把ur.* 删掉,把 u.* 用户表的信息加上,中间表只是作为连接条件
 
 * 上面第二步查询出的字段中 这个角色表的id 和用户表的 id 重名了,所以我们给角色表的id字段起个别名
 所以sql 语句编写如下:
 SELECT r.id AS rid,r.`ROLE_NAME`,r.`ROLE_DESC`,u.* FROM role r LEFT OUTER JOIN user_role ur ON r.`id`=ur.`RID` LEFT OUTER JOIN USER u ON u.`id`=ur.`UID`
 

8.sql 语句编写好后,我们在实体类中来体现多对多的关系

1.我们在角色的实体类中提供一个集合,用来描述多对多的关系
​
public class Role implements Serializable {
    private Integer id;
    private String roleName;
    private String roleDesc;
    //提供一个集合,来描述多对多的关系,集合里面放的是User类
    private List users;
    //get set 方法略 自己补上
 }   

9.在角色的接口中提供方法

public interface IRoleDao {
    //查询所有角色对应的用户信息
    List findAll();
}

10.在角色接口的 IRoleDao.xml 映射文件中进行配置

* 配置角色实体类和角色表的映射关系,注意我的角色实体类中的属性名没有和表中的字段名保持一致,所以配的时候注意
collection 标签中的两个属性:
* property="users" 角色表中维护的那个集合对象
* ofType="org.westos.domain.User" 集合中装的什么类型
​
​
 
        
        
        
        
        
        
            
            
            
            
            
            
        
    

11.把配置查询的返回类型,以及sql语句

1.把我们刚才测试好的sql语句粘贴进来,以及返回类型修改为我们配置的映射id名
    

12.测试

    * @Before @After 中的代码略了 ,注意一下
    
    @Test
    public void testFindAll(){
        IRoleDao dao = sqlSession.getMapper(IRoleDao.class);
        List list = dao.findAll();
        for (Role role : list) {
            System.out.println(role);
            //获取角色的所属用户
            List users = role.getUsers();
            System.out.println(users);
        }
    }

下来就是查询该用户有哪些角色

1.在用户的接口中提供方法

public interface IUserDao {
    //查询该用户都有哪些角色
    List findAll();
}
​

2.在用户的实体类中,维护一个集合,用来描述多对多的关系

public class User implements Serializable {
 
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    //提供一个集合用来描述一个用户有多个角色
    private List roles;
   //get set 方法略,自己补上   
}

3.修改SQL语句

把我们刚才查询该角色属于哪个用户用的左外连接,修改成右外连接,
就可以查询出,所有用户有哪些角色
 SELECT r.id AS rid, r.`ROLE_NAME`, r.`ROLE_DESC`, u.*
        FROM role r
                 RIGHT JOIN user_role ur ON r.`ID` = ur.`RID`
                 RIGHT JOIN USER u ON ur.`UID` = u.`id`

4.在IUserDao.xml 映射文件中编写配置


        
        
        
        
        
        
​
        
        
            
            
            
            
        
    
    
    
    

5.测试

   @Test
    public void testFindAll() throws IOException {
        //获取接口的代理对象
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        //执行查询操作
        List list = userDao.findAll();
        for (User user : list) {
            System.out.println(user);
            //获取该用户右哪些角色
            List roles = user.getRoles();
            System.out.println(roles);
​
        }
    }

你可能感兴趣的:(MyBatis,mybatis,数据库,java)