Mybatis(五)


Mybatis(五)

Mybatis是一款优秀的持久层框架,用于简化JDBC的开发。

入门程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//mapper包下
package com.ljsblog.mapper;

import com.ljsblog.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface UserMapper {
@Select("select * from user")
public List<User> userList();
}


//pojo包下
package com.ljsblog.pojo;

public class User {
private Integer id;
private String name;
private short age;
private short gender;
private String phone;

public User() {
}

public User(Integer id, String name, short age, short gender, String phone) {
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
this.phone = phone;
}

/**
* 获取
* @return id
*/
public Integer getId() {
return id;
}

/**
* 设置
* @param id
*/
public void setId(Integer id) {
this.id = id;
}

/**
* 获取
* @return name
*/
public String getName() {
return name;
}

/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}

/**
* 获取
* @return age
*/
public short getAge() {
return age;
}

/**
* 设置
* @param age
*/
public void setAge(short age) {
this.age = age;
}

/**
* 获取
* @return gender
*/
public short getGender() {
return gender;
}

/**
* 设置
* @param gender
*/
public void setGender(short gender) {
this.gender = gender;
}

/**
* 获取
* @return phone
*/
public String getPhone() {
return phone;
}

/**
* 设置
* @param phone
*/
public void setPhone(String phone) {
this.phone = phone;
}

public String toString() {
return "User{id = " + id + ", name = " + name + ", age = " + age + ", gender = " + gender + ", phone = " + phone + "}";
}
}

//application.properties
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
spring.datasource.username=root
spring.datasource.password=root

package com.ljsblog;


//Test/java/com.ljsblog
import com.ljsblog.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SpringbootmybatisApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void userList(){
userMapper.userList().stream().forEach(s-> System.out.println(s));
}

}

JDBC

JDBC:Java DataBase Connectivity,就是使用java语言操作关系型数据库的一套API。

sun公司官方定义一套操作所有关系型数据库的规范,即接口,各个数据库厂商(Mysql,Oracle等)去实现该接口,提供数据库驱动jar包,我们可用该接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

数据库连接池

数据库连接池是个容器,负责分配,管理数据库连接(Connection)

它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。

释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏。

优势

  • 资源重用
  • 提升系统响应速度
  • 避免数据库连接遗漏。

现常用数据库连接池产品

  • Druid
  • Hikari(Springboot默认)

若使用Druid需引入依赖

1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>

lombok工具包

Lombok是一个实用的java类库,能通过注解的形式自动生成构造器,getter/setter,equals,hashcode,toString等方法,并可以自动化生成日志变量,简化Java开发,提高效率。

需引入依赖

1
2
3
4
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

注解

  • @Getter/@Setter
    • 为所有属性提供get/set方法
  • @ToString
    • 会给类自动生成易阅读的toString方法
  • @EqualsAndHashCode
    • 根据类所拥有的非静态字段自动重写equals方法和hashCode方法
  • @Data
    • 提供更综合的生成代码功能,相当于@Getter+@Setter+@ToString+@EqualsAndHashCode
  • @NoArgsConstructor
    • 为实体类生成无参的构造器方法
  • @AllArgsConstructor
    • 为实体类生成除了static修饰的字段之外带有各个参数的构造器方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.ljsblog.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String name;
private short age;
private short gender;
private String phone;
}

Mybatis基础操作

参数占位符

  • #{…}
    • 执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值
    • 使用时机:参数传递,都使用#{…}
  • ${…}
    • 拼接SQL,直接将参数拼接在SQL语句中,存在SQL注入问题
    • 使用时机:若对表名,列表进行动态设置时使用

删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Mapper
package com.ljsblog.mapper;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface EmpMapper {
@Delete("delete from emp where id=#{id}")
public void delete(Integer id);
}

//Test
@Test
public void delete(){
empMapper.delete(17);
}

:若mapper接口方法形参只有一个普通类型的参数,#{…}里面的属性名可以随便写。

日志输出

可在application.properties中,打开mybatis的日志,并指定输出到控制台。

mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

添加(新增)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time) " +"values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},{updateTime})")
public void insert(Emp emp);

@Test
public void insert(){
Emp emp=new Emp();
emp.setUsername("Jerry");
emp.setName("杰瑞");
emp.setGender((short)1);
emp.setImage("1.jpg");
emp.setJob((short)1);
emp.setEntrydate(LocalDate.of(2000,1,1));
emp.setCreateTime(LocalDateTime.now());
emp.setUpdateTime(LocalDateTime.now());
emp.setDeptId(1);
empMapper.insert(emp);
}

主键返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Options(useGeneratedKeys = true,keyProperty = "id")//获取返回的主键,并将其存入emp的id变量中
@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time) " +
"values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
public void insert(Emp emp);

@Test
public void insert(){
Emp emp=new Emp();
emp.setUsername("Tom");
emp.setName("汤姆");
emp.setGender((short)1);
emp.setImage("1.jpg");
emp.setJob((short)1);
emp.setEntrydate(LocalDate.of(2000,1,1));
emp.setCreateTime(LocalDateTime.now());
emp.setUpdateTime(LocalDateTime.now());
emp.setDeptId(1);
empMapper.insert(emp);
System.out.println(emp.getId());
}

更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Update("update emp set username=#{username},name=#{name},gender=#{gender},image=#{image},job=#{job},entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} where id=#{id}")
public void update(Emp emp);

@Test
public void update(){
Emp emp=new Emp();
emp.setId(21);
emp.setUsername("Tom1");
emp.setName("汤姆1");
emp.setGender((short)2);
emp.setImage("2.jpg");
emp.setJob((short)2);
emp.setEntrydate(LocalDate.of(2001,1,1));
emp.setUpdateTime(LocalDateTime.now());
emp.setDeptId(2);
empMapper.update(emp);
}

查询

根据id查询

数据封装

  • 实体类属性名和数据库表查询返回的字段名一致,mybatis会自动封装
  • 若实体类属性名和数据库表查询返回的字段名不一致,不能自动封装

开启驼峰命名:若字段名与属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射,例如dept_id会变成deptId。

开启驼峰命名需在application.properties文件里加入以下代码:

mybatis.configuration.map-underscore-to-camel-case=true。

1
2
3
4
5
6
7
8
9
@Select("select * from emp where id=#{id}")
public Emp select(int id);

@Test
public void select(){
System.out.println(empMapper.select(21));
}

mybatis.configuration.map-underscore-to-camel-case=true。

条件查询

1
2
3
4
5
6
7
8
//sql,concat,拼接字符串
@Select("select * from emp where name like concat('%',#{name},'%') and gender=#{gender} and entrydate between #{begin} and #{end} order by update_time desc")
public List<Emp> select1(String name, Short gender, LocalDate begin, LocalDate end);

@Test
public void select1(){
System.out.println(empMapper.select1("张",(short)1,LocalDate.of(2010,1,1),LocalDate.of(2020,1,1)));
}

XML映射文件

规范

  • XML映射文件的名称和Mapper接口名称一致,并且将XML映射文件和Mapper放在相同名称的包下(同包同名)。
  • XML映射文件的namespace属性与Mapper接口全限定名一致
  • XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型的一致。

范例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public List<Emp> select2(String name, Short gender, LocalDate begin, LocalDate end);


<?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">
<!--以上为固定,从https://mybatis.net.cn/getting-started.html复制-->
<mapper namespace="com.ljsblog.mapper.EmpMapper">
<!-- resultType指单条记录所封装的类型-->
<select id="select2" resultType="com.ljsblog.pojo.Emp">
select * from emp where name like concat('%',#{name},'%') and gender=#{gender} and entrydate between #{begin} and #{end} order by update_time desc
</select>
</mapper>

注解方式和XML方式

  • 若执行简单的增删改查功能,使用注解。

  • 若执行复杂的SQL功能,使用XML。

Mybatis动态sql

随着用户的输入或外部条件的变化而变化的语句,称为动态sql

标签

1
2
3
4
5
6
7
8
9
10
11
<if>用于判断条件是否成立,使用test属性进行条件判断,若条件为true,则拼接SQL
<where>where元素只会在子元素有内容的情况才能插入where子句,而且会自动去除子句开头的AND或OR
<set>动地在行首插入set关键字,并会删掉额外的逗号,用在update语句中
<foreach>遍历,属性:
collection:集合名称
item:结合遍历出来的元素/项
separator:每次遍历使用的分隔符
open:遍历开始前拼接的片段
close:遍历结束后拼接的片段
<sql>定义可重用的SQL片段,属性值id
<include>通过属性refid,指定包含的sql片段

范例1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public List<Emp> select2(String name, Short gender, LocalDate begin, LocalDate end);

<?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">
<!--以上为固定,从https://mybatis.net.cn/getting-started.html复制-->
<mapper namespace="com.ljsblog.mapper.EmpMapper">
<!--resultType指单条记录所封装的类型-->
<select id="select2" resultType="com.ljsblog.pojo.Emp">
select *
from emp
<where>
<if test="name!=null">
name like concat('%', #{name}, '%')
</if>
<if test="gender!=null">
and gender = #{gender}
</if>
<if test="begin!=null and end!=null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time desc
</select>
</mapper>

@Test
public void select2(){
System.out.println(empMapper.select2("张",null,null,null));
}

范例2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public void update1(Emp emp);

<update id="update1">
update emp
<set>
<if test="username!=null">
username=#{username},
</if>
<if test="name!=null">
name=#{name},
</if>
<if test="gender!=null">
gender=#{gender},
</if>
<if test="image!=null">
image=#{image},
</if>
<if test="job!=null">
job=#{job},
</if>
<if test="entrydate!=null">
entrydate=#{entrydate},
</if>
<if test="deptId!=null">
dept_id=#{deptId},
</if>
<if test="updateTime!=null">
update_time=#{updateTime}
</if>
</set>
where id = #{id}
</update>

@Test
public void update1(){
Emp emp=new Emp();
emp.setId(21);
emp.setUsername("Tom5");
emp.setName("汤姆5");
emp.setGender((short)3);
emp.setDeptId(1);
empMapper.update1(emp);
}

范例3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void delete1(List<Integer> ids);

<delete id="delete1">
delete from emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>

@Test
public void delete1(){
List<Integer> ids= Arrays.asList(10,11);
empMapper.delete1(ids);
}

范例4:

1
2
3
4
5
6
7
8
9
10
11
12
public List<Emp> selectAll();

<sql id="all">select,id,username,password,name,gender,image,job,entrydate,dept_id,create_time,update_time</sql>
<select id="selectAll" resultType="com.ljsblog.pojo.Emp">
<include refid="all"/> from emp
</select>

@Test
public void allSelect(){
List<Emp> empList=empMapper.selectAll();
System.out.println(empList);
}

Author: ljs
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source ljs !
评论
  TOC