MyBatis (二) -- MyBatis中的 查询 & 增删改 & 动态SQL语句 & 注解开发

1 解决列名和属性名不匹配的问题

默认情况下, MyBatis会进行自动映射(Auto-Mapping), 指的是MyBatis能够自动将同名的列和属性进行映射

1.1 在 SQL 语句中给列名起别名

 SQL语句复用度低  无法处理多变关联查询问题




    

1.2 让MyBatis自动解决

在MyBatis核心配置文件中开启自动驼峰命名, 当MyBatis发现有带下划线的列名时, 会自动转换为对应的驼峰命名.

例如: reg_time --> regTime.

注意: settings标签要配置在environments标签的前面.



    
    

1.3 定义映射关系

映射关系可以在多处使用 可以处理数据库表格之间一对一 一对多  多对多的关系




    
    
        
        
        
        
        
        
        
        
        
    

    

2 查询常用的三种方法

三个常用的查询方法: selectList, selectOne和selectMap, 都允许在调用的时候传递参数, 参数的类型是Object, 个数只能传递一个. 如果需要传递多个参数, 需要处理成单个对象. 同时, SQL语句也需要相应的修改, 要使用占位符替代接收的参数.

2.1 selectList

用于查询多条数据, MyBatis会自动将查到的数据封装为List集合.

最常用, 查不到时返回空集合, 而不是null.

2.2 selectOne

用于查询单条数据, 结果是指定的某个对象或者某个值. 很常用. 底层调用了selectList, 如果查到一个值, 直接返回结果,

如果查到多个值, 抛出异常, 如果查不到, 返回null.

MyBatis (二) -- MyBatis中的 查询 & 增删改 & 动态SQL语句 & 注解开发_第1张图片

2.3 selectMap

用于将查询结果转换为Map集合, 使用时需要指定将结果中的哪个属性作为map的key, Map的value就是当前对象.

一般不用. 底层调用selectList.

MyBatis (二) -- MyBatis中的 查询 & 增删改 & 动态SQL语句 & 注解开发_第2张图片

3 占位符

占位符有两种, 分别是#{}, ${}.

#{}底层使用的是PreparedStatement, ${}底层使用的是Statement.

3.1 #{} 占位符

#{}作为SQL语句占位符时, MyBatis允许接收三种类型的参数:

1)简单类型的参数

 

简单类型指的是基本数据类型, 包装类型, String, java.sql.*...,

此时, #{}会忽略占位符的名称和个数, 将参数进行绑定. parameterType可以指定参数的类型, 如果省略, 表示参数类型为Object.

一旦指定, 传参时必须类型一致, 否则抛出类型转换异常.

@Test

  public void testSelById() {

    SqlSession session = MyBatisUtil.getSession();

    session.selectOne("selById", 3);

    session.close();

}

 2)Map类型的参数

多个参数传递时使用, 将多个参数封装为Map集合, #{}需要使用Map中对应的key去取值, 如果key不存在, 不会报错, 拿到的是null

@Test

  public void testSel4LoginByMap() {

    SqlSession session = MyBatisUtil.getSession();

    Map params = new HashMap<>();

    params.put("uname", "lisi");

    params.put("upwd", "123");

    session.selectOne("sel4Login", params);

    session.close();

}

3)POJO类型的参数

多个参数封装为对应的POJO类, 此时, #{}需要调用该POJO类中对应的 getter 方法取值, 如果没有对应的getter, 则抛出异常.

@Test

  public void testSel4LoginByPojo() {

    SqlSession session = MyBatisUtil.getSession();

    User user = new User();

    user.setUsername("wangwu");

    user.setPassword("123");

    session.selectOne("sel4Login", user);

    session.close();

}

当SQL语句结构不确定时, 不能使用#{}占位符,

原因是#{}底层使用的是PreparedStatement, 会对SQL语句进行预编译, 导致SQL语句的结构无法被补全.

使用${}来进行操作.

3.2 ${}占位符

${}底层使用的是Statement实现, 做的是字符串的直接拼接.

SQL语句结构固定的情况下, 应该使用#{}占位符, 当SQL语句结构不确定是, 只能使用${}实现.


@Test
public void test() {
    SqlSession session = MyBatisUtil.getSession();

    Map params = new HashMap<>();
    params.put("tbName", "tb_user");
    params.put("cname", "reg_time");
    params.put("cvalue", "2019-12-24 15:18:35");
    params.put("order", "order by id desc");

    session.selectList("sel", params);
    session.close();
}

4 实现增删改操作

增删改操作涉及到事务管理, MyBatis中, 默认将JDBC的自动管理事务机制关闭了. 要求所有增删改操作都必须进行手动的事务管理. 通过SqlSession来进行事务管理.

4.1  新增数据

  • 标签: 使用标签
  • 方法: 使用insert()
  • useGeneratedKeys=”true”表示要获取自动增长的主键, keyProperty=”id”表示将获取到的主键值赋值给id属性, 会自动调用setId方法


    insert into tb_user values (
        default, #{username}, #{password}, #{realName}, #{age}, #{birthday}, now()
    )

@Test
public void testInsert() {
    SqlSession session = MyBatisUtil.getSession();
    User user = new User(20, "zhaomin3", "123", "赵敏", new Date());
    // 新增前打印user对象
    System.out.println(user);
    int rows = session.insert("ins", user);
    if(rows == 1) {
        // 提交事务
        session.commit();
        System.out.println("ok");
    } else {
        System.out.println("error");
    }
    // 新增后打印user对象
    System.out.println(user);

    session.close();
}

4.2 更新数据

  • 标签: 使用标签
  • 方法: 使用update()


    update tb_user set username=#{uname}, real_name=#{rname} where id=#{id}

@Test
public void testUpdate() {
    SqlSession session = MyBatisUtil.getSession();

    Map params = new HashMap<>();
    params.put("uname", "xiexun");
    params.put("rname", "谢逊");
    params.put("id", 9);

    try {
        session.update("upd", params);
        session.commit();
    } catch (Exception e) {
        session.rollback();
        e.printStackTrace();
    }

    session.close();
}

4.3 删除数据

  • 标签: 使用标签
  • 方法: 使用delete()


    delete from tb_user where id=#{id}

@Test
public void testDelete() {
    SqlSession session = MyBatisUtil.getSession();
    session.delete("del", 8);
    session.commit();
    session.close();
}

5 类型别名

主要针对映射文件中定位类型时使用, 简化配置. 分为两种情况:

5.1 MyBatis内建别名

这是一些为常见的 Java 类型内建的相应的类型别名。它们都是不区分大小写的,注意对基本类型名称重复采取的特殊命名风格。

别名

映射的类型

别名

映射的类型

别名

映射的类型

_byte

byte

string

String

decimal

BigDecimal

_long

long

byte

Byte

bigdecimal

BigDecimal

_short

short

long

Long

object

Object

_int

int

short

Short

map

Map

_integer

int

int

Integer

hashmap

HashMap

_double

double

integer

Integer

list

List

_float

float

double

Double

arraylist

ArrayList

_boolean

boolean

float

Float

collection

Collection

 

 

boolean

Boolean

iterator

Iterator

 

 

date

Date

 

 

 

 

 

 

 

 

 

 

 

 

 

5.2 自定义别名


    
    

6 动态SQL语句

MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态SQL这一特性可以彻底摆脱这种痛苦。

6.1

用于条件判断, test属性表示判断结果, 要求是一个boolean值.

6.2

用于维护where子句, 通常配合一起使用. 如下功能:

  • 当没有条件时, 不会创建WHERE关键字;
  • 当有条件时, 会自动生成WHERE关键字;
  • 会自动去掉第一个条件的and/or关键字.


    

  

6.3

功能类似于java中的switch...case...default. 多分支判断, 只能成立一个条件.

6.4

对数据进行加工, 通常用于处理模糊查询的数据.

6.5

提取SQL片段和引用SQL片段



    
        
        select id, username, password, real_name, 
        age, birthday, reg_time from tb_user
    

    
  

6.6

用于维护更新语句中的set子句, 类似于的功能.

  • 当条件不成立时, 不会创建SET关键字;
  • 当条件成立时, 会自动生成SET关键字;
  • 会自动去掉最后一个条件的逗号(,).

    update tb_user
        
            id = #{id},
            
                username=#{username},
            
            
                password=#{password},
            
            
                age=#{age},
            
        
    where id=#{id}

6.7

对数组, List, Set, Map集合进行遍历时使用, 通常用于in操作中. 一般用于实现批量新增或批量删除操作. 属性介绍:

  • collection: 要遍历的集合
  • item: 迭代项
  • open: 以什么字符开头
  • close: 以什么字符结束
  • separator: 多个迭代项之间的分隔符

    delete from tb_user where id in
    
        #{id}
    
 
@Test
  public void testForeach() {
    SqlSession session = MyBatisUtil.getSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    // int[] ids = {1, 2, 3, 4, 5, 6};
    // List ids = new ArrayList<>();
    // Set ids = new HashSet<>();
    // Collections.addAll(ids, 1, 3, 5, 7);
    Map ids = new HashMap<>();
    ids.put(1, 11);
    ids.put(2, 22);
    ids.put(3, 33);
    mapper.delUser(ids);
    session.close();
}

6.8 >

用于对数据进行处理, 可以在指定的字符串前后进行操作.


    insert into tb_user values
    
        
            ,default, #{u.username}, #{u.password}, #{u.realName},
             #{u.age}, #{u.birthday}, now(),
        
    
  

6.9 标签的使用

默认情况下, MyBatis会进行自动映射(Auto-Mapping), 数据库表格的列名和对象的属性名如果同名, MyBatis会进行自动赋值. 当列名和属性名不同., MyBatis允许程序员自己定义列名和属性名的映射关系.

需要配置resultMap属性使用.

如果使用了resultType属性, 表示自动映射, 如果使用了resultMap属性, 表示手动映射.

  • 同名可以省略不写;
  • id标签要写在result标签的前面;



    
    
        
        
        
        
        
        
        
        
        
    

    

8  多表连接查询

在MyBatis中, 多表连接查询主要分为两种, 一种是多对一, 一种是一对多.

示例数据 

create table tb_class (
    id integer primary key auto_increment,
    name varchar(10) not null,
    room varchar(10)
);

# 创建学生表
create table tb_student (
    id integer primary key auto_increment,
    name varchar(20) not null,
    gender char(1),
    birthday date,
    cid integer
);

# 添加数据
insert into tb_class values
(default, 'Java', '1601'),
(default, '计算机网络', '1602'),
(default, '数据结构', '1601');

insert into tb_student values
(default, '张三', '男', '1998-12-12', 1),
(default, '李四', '女', '1999-12-12', 2),
(default, '王五', '男', '1998-12-12', 2),
(default, '赵六', '男', '1998-12-12', 3),
(default, '孙七', '女', '1998-12-12', 3),
(default, '吴八', '女', '1998-12-12', 3);

8.1 多对一查询

   多个学生对应一个班级, 查询所有学生信息, 同时查询每个学生所在班级的信息

8.1.1 实体类

在学生实体类中, 应该提供一个班级类型的对象, 用来表示班级信息.

public class Student implements Serializable {
    private Integer id;
    private String name, gender;
    private Date birthday;
    private Integer cid;
    private Clazz clazz;
}

8.1.2 关联方式实现查询

指的是通过SQL语句关联查询的方式实现. 表1 joint 表2 on 关联条件.

在MyBatis中, 关联单个对象需要使用标签进行.




    
        
        
            
            
        
    

    

8.1.3 N+1方式实现

指的是完成本次查询一共需要执行N+1条SQL语句. 每条SQL都是单表查询.


    
        
        
    

    

8.2  一对多查询

指的是一个班级有多个学生, 查询班级时把当前班级的所有学生也查到.

8.2.1 实体类

public class Clazz implements Serializable {
    private Integer id;
    private String name, room;
    private List list = new ArrayList<>();
}

8.2.2 关联方式实现


    
        
        
            
            
            
        
    

    

8.2.3 N+1方式实现



    
        
        
    

    

 

9 Mybatis的注解开发

MyBatis中常用的注解,使用MyBatis中的注解, 可以简化映射文件的配置. 注意, 动态SQL不能简化.

  • @Select, 用于简化查询配置
  • @Insert, 用于简化新增配置
  • @Update, 用于简化更新配置
  • @Delete, 用于简化删除配置
public interface DemoMapper {
    @Select("select * from tb_user")
    List selAll();

    @Delete("delete from tb_user where id=#{id}")
    void delById(int id);
}

注解模式使用注意事项

1使用注解的接口可以同时存在mapper映射文件

2接口上使用了注解 在映射文件中就不能在定义对应的SQL语句标签

3使用了注解的接口 接口中并不是所有的方法都必须使用注解 个别方法使用映射文件OK

注解模式开发的好处

简化mapper映射文件

注解模式开发的缺点

将SQL语句转移到了代码中  修改代码需要重新编译项目 耦合度高

没有办法独立处理一对一 一对多  多对多的关联关系

什么情况下使用注解开发?

1业务逻辑简单

2业务逻辑稳定

你可能感兴趣的:(java学习,MySQL)