0
点赞
收藏
分享

微信扫一扫

狂神说Java Mybatis笔记

穆风1818 2022-06-28 阅读 29


MyBatis
1、简介
1.1 什么是Mybatis

MyBatis 是一款优秀的持久层框架;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

1.2 持久化 

持久化就是将程序的数据在持久状态和瞬时状态转化的过程。

内存:断电即失。数据库(Jdbc),io文件持久化。

为什么要持久化?

有一些对象,不能让他丢掉。内存太贵

1.3 持久层
Dao层、Service层、Controller层

完成持久化工作的代码块
层界限十分明显
1.4 为什么需要MyBatis
帮助程序员将数据存入到数据库中,方便,传统的JDBC代码太复杂了,简化,框架,自动化,不用MyBatis也可以,技术没有高低之分

优点:

简单易学,灵活

sql和代码的分离,提高了可维护性。
提供映射标签,支持对象与数据库的orm字段关系映射
提供对象关系映射标签,支持对象关系组建维护
提供xml标签,支持编写动态sql
2、第一个Mybatis程序
思路:搭建环境 --> 导入MyBatis --> 编写代码 --> 测试

2.1 搭建环境
新建项目

创建一个普通的maven项目

删除src目录 (就可以把此工程当做父工程了,然后创建子工程)

导入maven依赖

<!--导入依赖-->

<dependencies>
<!--mysqlq驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.12</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>

 

一般情况下,我们用到的资源文件(各种xml,properites,xsd文件等)都放在src/main/resources下面,利用maven打包时,maven能把这些资源文件打包到相应的jar或者war里。

 

有时候,比如mybatis的mapper.xml文件,我们习惯把它和Mapper.java放一起,都在src/main/java下面,这样利用maven打包时,就需要修改pom.xml文件,来把mapper.xml文件一起打包进jar或者war里了,否则,这些文件不会被打包的。(maven认为src/main/java只是java的源代码路径)。

添加build

<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
<ild>

 

创建一个Module

2.2 创建一个模块(可能会报中文的错误,把utf-8改为utf8)
编写mybatis的核心配置文件(mybatis-config.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核心配置文件-->
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
</configuration>

 

编写mybatis工具类

//sqlSessionFactory --> sqlSession
public class MybatisUtils {

static SqlSessionFactory sqlSessionFactory = null;

static {
try {
//使用Mybatis第一步 :获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}

//既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例.
// SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}

 

2.3 编写代码
实体类

Dao接口

public interface UserDao {
public List<User> getUserList();
}

接口实现类 (由原来的UserDaoImpl转变为一个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">

<!--namespace=绑定一个指定的Dao/Mapper接口-->
<mapper namespace="com.kuang.dao.UserDao">
<select id="getUserList" resultType="com.kuang.pojo.User">
select * from USER
</select>
</mapper>

编写实体类

package com.bupt.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class User {
private int id;
private String username;

}

 

测试

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

import com.bupt.dao.UserDao;
import com.bupt.pojo.User;
import com.bupt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;

public class test {
@Test
public void test01(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
User userById = mapper.getUserById(1);
System.out.println(userById);
sqlSession.close();
}

//增删改必须提交事务
@Test
public void testInsert(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
int i = mapper.addUser(new User(2, "梨花"));
if(i > 0){
System.out.println("插入成功");
}
sqlSession.commit();
sqlSession.close();
}

@Test
public void updateUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
mapper.updateUser(new User(2,"刘雷"));
sqlSession.commit();
sqlSession.close();
}

@Test
public void testDelete(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
int i = mapper.deleteUser(30);
sqlSession.commit();
sqlSession.close();
}
//实现模糊查询
@Test
public void testLike(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userLike = mapper.getUserLike("%张%");
for (User user:userLike){
System.out.println(user);
}
sqlSession.close();
}

@Test
public void testLike1(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> zhang = mapper.getUserLike1("张");
for (User user:zhang){
System.out.println(user);
}
sqlSession.close();
}

@Test
public void testMap(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
HashMap<String, Object> map = new HashMap<>();
map.put("id",4);
map.put("username","王虎");
map.put("birthday","2021-03-27");
map.put("sex",1);
map.put("address","北京");
int i = mapper.insertUser(map);
sqlSession.commit();
sqlSession.close();
}
}

View Code

 

注意点:

org.apache.ibatis.binding.BindingException: Type interface com.kuang.dao.UserDao is not known to the MapperRegistry.

MapperRegistry是什么?

核心配置文件中注册mappers

狂神说Java Mybatis笔记_java_03

 

junit测试

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

@Test
public void test(){

//1.获取SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//2.执行SQL
// 方式一:getMapper
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
for (User user : userList) {
System.out.println(user);
}

//关闭sqlSession
sqlSession.close();
}

View Code

 

可能会遇到的问题:

  • 配置文件没有注册
  • 绑定接口错误
  • 方法名不对
  • 返回类型不对
  • Maven导出资源问题

3、CURD
1. namespace
namespace中的包名要和Dao/Mapper接口的包名一致

2. select
选择,查询语句;

id:就是对应的namespace中的方法名;

resultType : Sql语句执行的返回值;

parameterType : 参数类型;

编写接口

public interface UserMapper {
//查询所有用户
public List<User> getUserList();
//插入用户
public void addUser(User user);
}

 

编写对应的mapper中的sql语句

<insert id="addUser" parameterType="com.kuang.pojo.User">
insert into user (id,name,password) values (#{id}, #{name}, #{password})
</insert>

 

测试

@Test
public void test2() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User(3,"黑子","666");
mapper.addUser(user);
//增删改一定要提交事务
sqlSession.commit();

//关闭sqlSession
sqlSession.close();
}

 

注意:增删改查一定要提交事务:

sqlSession.commit();
增删改查全部流程实现

配置依赖和让资源文件能不导出

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>

<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>

View Code

db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/student?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username=root
password=root

mybatis-config.xml进行核心配置

1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE configuration
3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
5 <!--configuration核心配置文件-->
6 <configuration>
7 <properties resource="db.properties"/>
8 <environments default="development">
9 <environment id="development">
10 <transactionManager type="JDBC"/>
11 <dataSource type="POOLED">
12 <property name="driver" value="${driver}"/>
13 <property name="url" value="${url}"/>
14 <property name="username" value="${username}"/>
15 <property name="password" value="${password}"/>
16 </dataSource>
17 </environment>
18 </environments>
19 <mappers>
20 <mapper resource="com/bupt/dao/UserDaoMapper.xml"></mapper>
21 </mappers>
22 </configuration>

配置类MybatisUtils 获取sqlsession

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 package com.bupt.utils;
2
3 import org.apache.ibatis.io.Resources;
4 import org.apache.ibatis.session.SqlSession;
5 import org.apache.ibatis.session.SqlSessionFactory;
6 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
7
8 import java.io.IOException;
9 import java.io.InputStream;
10
11
12 public class MybatisUtils {
13 static SqlSessionFactory factory = null;
14 static {
15 String resource = "mybatis-config.xml";
16 try {
17 InputStream resourceAsStream = Resources.getResourceAsStream(resource);
18 factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
19
20 } catch (IOException e) {
21 e.printStackTrace();
22 }
23 }
24 public static SqlSession getSqlSession(){
25 return factory.openSession();
26 }
27 }

View Code

实体类(默认和数据库对应)

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 package com.bupt.pojo;
2
3 import lombok.AllArgsConstructor;
4 import lombok.Data;
5
6 @Data
7 @AllArgsConstructor
8 public class User {
9 private int id;
10 private String username;
11
12 }

View Code

增删改查的接口UserDao

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 package com.bupt.dao;
2
3 import com.bupt.pojo.User;
4
5 import java.util.List;
6 import java.util.Map;
7
8 public interface UserDao {
9
10 //查询
11 User getUserById(int id);//查询
12
13 //insert一个用户
14 int addUser(User user);
15
16 //更新一个用户
17 int updateUser(User user);
18
19 //删除
20 int deleteUser(int id);
21
22 int insertUser(Map<String,Object> map);
23
24 //模糊查询
25 List<User> getUserLike(String name);
26 List<User> getUserLike1(String name);
27 }

View Code

增删改查的具体实现UserDaoMapper.xml

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper
3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5 <mapper namespace="com.bupt.dao.UserDao">
6
7 <select id="getUserById" resultType="com.bupt.pojo.User" parameterType="int">
8 select * from user where id = #{id}
9 </select>
10
11 <!-- 对象中的属性可以直接取出来-->
12 <insert id="addUser" parameterType="com.bupt.pojo.User" >
13 insert into user (id, username) values(#{id},#{username});
14 </insert>
15
16 <update id="updateUser" parameterType="com.bupt.pojo.User">
17 update user set username=#{username} where id=#{id};
18 </update>
19
20 <delete id="deleteUser" parameterType="int">
21 delete from user where id=#{id};
22 </delete>
23
24 <select id="getUserLike" parameterType="String" resultType="com.bupt.pojo.User">
25 select * from user where username like #{name}
26 </select>
27
28 <select id="getUserLike1" parameterType="String" resultType="com.bupt.pojo.User">
29 select * from user where username like "%"#{name}"%"
30 </select>
31
32 <insert id="insertUser" parameterType="map" >
33 insert into user (id,username,birthday,sex,address) values (#{id},#{username},#{birthday},#{sex},#{address});
34 </insert>
35
36 </mapper>

View Code

别忘了在mybatis配置文件注册Mapper

<mappers>
<mapper resource="com/bupt/dao/UserDaoMapper.xml"></mapper>
</mappers>

进行测试

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 import com.bupt.dao.UserDao;
2 import com.bupt.pojo.User;
3 import com.bupt.utils.MybatisUtils;
4 import org.apache.ibatis.session.SqlSession;
5 import org.junit.Test;
6
7 import java.util.HashMap;
8 import java.util.List;
9
10 public class test {
11 @Test
12 public void test01(){
13 SqlSession sqlSession = MybatisUtils.getSqlSession();
14 UserDao mapper = sqlSession.getMapper(UserDao.class);
15 User userById = mapper.getUserById(1);
16 System.out.println(userById);
17 sqlSession.close();
18 }
19
20 //增删改必须提交事务
21 @Test
22 public void testInsert(){
23 SqlSession sqlSession = MybatisUtils.getSqlSession();
24 UserDao mapper = sqlSession.getMapper(UserDao.class);
25 int i = mapper.addUser(new User(2, "梨花"));
26 if(i > 0){
27 System.out.println("插入成功");
28 }
29 sqlSession.commit();
30 sqlSession.close();
31 }
32
33 @Test
34 public void updateUser(){
35 SqlSession sqlSession = MybatisUtils.getSqlSession();
36 UserDao mapper = sqlSession.getMapper(UserDao.class);
37 mapper.updateUser(new User(2,"刘雷"));
38 sqlSession.commit();
39 sqlSession.close();
40 }
41
42 @Test
43 public void testDelete(){
44 SqlSession sqlSession = MybatisUtils.getSqlSession();
45 UserDao mapper = sqlSession.getMapper(UserDao.class);
46 int i = mapper.deleteUser(30);
47 sqlSession.commit();
48 sqlSession.close();
49 }
50 //实现模糊查询
51 @Test
52 public void testLike(){
53 SqlSession sqlSession = MybatisUtils.getSqlSession();
54 UserDao mapper = sqlSession.getMapper(UserDao.class);
55 List<User> userLike = mapper.getUserLike("%张%");
56 for (User user:userLike){
57 System.out.println(user);
58 }
59 sqlSession.close();
60 }
61
62 @Test
63 public void testLike1(){
64 SqlSession sqlSession = MybatisUtils.getSqlSession();
65 UserDao mapper = sqlSession.getMapper(UserDao.class);
66 List<User> zhang = mapper.getUserLike1("张");
67 for (User user:zhang){
68 System.out.println(user);
69 }
70 sqlSession.close();
71 }
72
73 @Test
74 public void testMap(){
75 SqlSession sqlSession = MybatisUtils.getSqlSession();
76 UserDao mapper = sqlSession.getMapper(UserDao.class);
77 HashMap<String, Object> map = new HashMap<>();
78 map.put("id",4);
79 map.put("username","王虎");
80 map.put("birthday","2021-03-27");
81 map.put("sex",1);
82 map.put("address","北京");
83 int i = mapper.insertUser(map);
84 sqlSession.commit();
85 sqlSession.close();
86 }
87 }

View Code

 

6. 万能Map
假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应该考虑使用Map!

UserMapper接口
//用万能Map插入用户

public void addUser2(Map<String,Object> map);

 

UserMapper.xml

<!--对象中的属性可以直接取出来 传递map的key-->
<insert id="addUser2" parameterType="map">
insert into user (id,name,password) values (#{userid},#{username},#{userpassword})
</insert>

测试

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 @Test
2 public void test3(){
3 SqlSession sqlSession = MybatisUtils.getSqlSession();
4 UserMapper mapper = sqlSession.getMapper(UserMapper.class);
5 HashMap<String, Object> map = new HashMap<String, Object>();
6 map.put("userid",4);
7 map.put("username","王虎");
8 map.put("userpassword",789);
9 mapper.addUser2(map);
10 //提交事务
11 sqlSession.commit();
12 //关闭资源
13 sqlSession.close();
14 }

View Code

 

  • Map传递参数,直接在sql中取出key即可! 【parameter=“map”】
  • 对象传递参数,直接在sql中取出对象的属性即可! 【parameter=“Object”】
  • 只有一个基本类型参数的情况下,可以直接在sql中取到
  • 多个参数用Map , 或者注解!

7. 模糊查询
模糊查询这么写?

Java代码执行的时候,传递通配符% %

<select id="getUserLike1" parameterType="String" resultType="com.bupt.pojo.User">
select * from user where username like #{name}
</select>

 

 1 List<User> userList = mapper.getUserLike("%李%"); 
在sql拼接中使用通配符

 1 <select id="getUserList2" resultType="com.bupt.pojo.User"> 2 select * from user where name like "%"#{name}"%" 3 </select> 

目前程序的框架为

狂神说Java Mybatis笔记_xml_20

 

 

 pom.xml

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 <?xml version="1.0" encoding="UTF8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <modelVersion>4.0.0</modelVersion>
6
7 <groupId>org.example</groupId>
8 <artifactId>Mybatis</artifactId>
9 <packaging>pom</packaging>
10 <version>1.0-SNAPSHOT</version>
11 <modules>
12 <module>mybatis-1-crud</module>
13 </modules>
14 <build>
15 <resources>
16 <resource>
17 <directory>src/main/java</directory>
18 <includes>
19 <include>**/*.properties</include>
20 <include>**/*.xml</include>
21 </includes>
22 <filtering>true</filtering>
23 </resource>
24 </resources>
25 </build>
26 <properties>
27 <maven.compiler.source>8</maven.compiler.source>
28 <maven.compiler.target>8</maven.compiler.target>
29 </properties>
30 <dependencies>
31 <dependency>
32 <groupId>mysql</groupId>
33 <artifactId>mysql-connector-java</artifactId>
34 <version>5.1.48</version>
35 </dependency>
36 <dependency>
37 <groupId>org.mybatis</groupId>
38 <artifactId>mybatis</artifactId>
39 <version>3.5.4</version>
40 </dependency>
41 <!--junit-->
42 <dependency>
43 <groupId>junit</groupId>
44 <artifactId>junit</artifactId>
45 <version>4.12</version>
46 <scope>test</scope>
47 </dependency>
48
49 </dependencies>
50
51 </project>

View Code

mybatis-config.xml

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration核心配置文件-->
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/myschool?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/bupt/dao/UserMapper.xml"/>
</mappers>
</configuration>

View Code

 

实体类User

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

package com.bupt.pojo;

import org.apache.ibatis.session.SqlSessionFactory;

import java.util.Objects;

public class User {
private int id;
private String name;
private String pwd;

public int getId() {
return id;
}

public String getName() {
return name;
}

public String getPwd() {
return pwd;
}

public void setId(int id) {
this.id = id;
}

public void setName(String name) {
this.name = name;
}

public void setPwd(String pwd) {
this.pwd = pwd;
}

public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}

public User() {
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return id == user.id && Objects.equals(name, user.name) && Objects.equals(pwd, user.pwd);
}

@Override
public int hashCode() {
return Objects.hash(id, name, pwd);
}
}

View Code

UserDao

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

package com.bupt.dao;

import com.bupt.pojo.User;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public interface UserDao {
//查询接口
List<User> getUserList();

User getUserById(int id);

//插入接口
public void addUser(User user);

//更新一个用户
public void updateUser(User user);

//删除一个用户
public void deleteUser(int id);

//插入用户
public void addUser2(Map<String, Object> map);

//模糊查询用户
List<User> getUserList2(String name);

}

View Code

UserMapper.xml

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--configuration核心配置文件-->
<mapper namespace="com.bupt.dao.UserDao">
<select id="getUserList" resultType="com.bupt.pojo.User">
select * from USER;
</select>

<select id="getUserById" parameterType="int" resultType="com.bupt.pojo.User">
select * from USER where id=#{id};
</select>

<insert id="addUser" parameterType="com.bupt.pojo.User">
insert into user (id,name,pwd) values (#{id},#{name},#{pwd});
</insert>

<update id="updateUser" parameterType="com.bupt.pojo.User">
update user set name=#{name}, pwd=#{pwd} where id=#{id};
</update>

<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>

<insert id="addUser2" parameterType="map">
insert into user(id,name) values(#{userid},#{username})
</insert>

<select id="getUserList2" resultType="com.bupt.pojo.User">
select * from user where name like "%"#{name}"%"
</select>
</mapper>

View Code

MybatisUtils

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 package com.bupt.utils;
2
3 import org.apache.ibatis.io.Resources;
4 import org.apache.ibatis.session.SqlSession;
5 import org.apache.ibatis.session.SqlSessionFactory;
6 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
7
8 import java.io.IOException;
9 import java.io.InputStream;
10
11 public class MybatisUtils {
12 static SqlSessionFactory build = null;
13 static {
14 String resources = "mybatis-config.xml";
15 try {
16 InputStream resourceAsStream = Resources.getResourceAsStream(resources);
17 build = new SqlSessionFactoryBuilder().build(resourceAsStream);
18
19 } catch (IOException e) {
20 e.printStackTrace();
21 }
22 }
23 public static SqlSession getSqlSession(){
24 return build.openSession();
25 }
26 }

View Code

 

经常碰到这样的面试题目:#{}和${}的区别是什么?
 
网上的答案是:#{}是预编译处理,$ {}是字符串替换。

mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;

mybatis在处理 $ { } 时,就是把 ${ } 替换成变量的值。

使用 #{} 可以有效的防止SQL注入,提高系统安全性。

sql注入指的是用户输入 or 1=1等变量导致原sql语句逻辑发生了变化,使得可以直接进入数据库,而使用预编译的方法可以让sql语句只把传入的数据当做参数进行处理

而不会改变原有sql的逻辑,preparestatement和#{}都是把变量预编译,防止sql注入。

 SQL注入详解 - myseries

4、配置解析

1. 核心配置文件

  • mybatis-config.xml
  • Mybatis的配置文件包含了会深深影响MyBatis行为的设置和属性信息。
1 configuration(配置)
2 properties(属性)
3 settings(设置)
4 typeAliases(类型别名)
5 typeHandlers(类型处理器)
6 objectFactory(对象工厂)
7 plugins(插件)
8 environments(环境配置)
9 environment(环境变量)
10 transactionManager(事务管理器)
11 dataSource(数据源)
12 databaseIdProvider(数据库厂商标识)
13 mappers(映射器)

2. 环境配置 environments
MyBatis 可以配置成适应多种环境

不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境

学会使用配置多套运行环境!

MyBatis默认的事务管理器就是JDBC ,连接池:POOLED

3. 属性 properties
我们可以通过properties属性来实现引用配置文件

这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。【db.poperties】

编写一个配置文件

db.properties

1 driver=com.mysql.cj.jdbc.Driver
2 url=jdbc:mysql://localhost:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
3 username=root
4 password=root

在核心配置文件中引入

<!--引用外部配置文件-->
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="root"/>
</properties>
  • 可以直接引入外部文件
  • 可以在其中增加一些属性配置
  • 如果两个文件有同一个字段,优先使用外部配置文件的

类型别名 typeAliases
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置.

意在降低冗余的全限定类名书写。

<!--可以给实体类起别名-->

<typeAliases>
<typeAlias type="com.kuang.pojo.User" alias="User"/>
</typeAliases>

 

也可以指定一个包,每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author,;若有注解,则别名为其注解值。见下面的例子:

<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>

 

在实体类比较少的时候,使用第一种方式。

如果实体类十分多,建议用第二种扫描包的方式。

第一种可以DIY别名,第二种不行,如果非要改,需要在实体上增加注解。

@Alias("author")
public class Author {
...
}

 

5. 设置 Settings
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。

 

6. 其他配置
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins 插件
mybatis-generator-core
mybatis-plus
通用mapper
7. 映射器 mappers
MapperRegistry:注册绑定我们的Mapper文件;

方式一:【推荐使用】

<!--每一个Mapper.xml都需要在MyBatis核心配置文件中注册-->
<mappers>
<mapper resource="com/kuang/dao/UserMapper.xml"/>
</mappers>

 

方式二:使用class文件绑定注册

<!--每一个Mapper.xml都需要在MyBatis核心配置文件中注册-->

<mappers>
<mapper class="com.kuang.dao.UserMapper"/>
</mappers>

 

注意点:

接口和他的Mapper配置文件必须同名
接口和他的Mapper配置文件必须在同一个包下
方式三:使用包扫描进行注入

<mappers>
<package name="com.kuang.dao"/>
</mappers>

 

8. 作用域和生命周期

声明周期和作用域是至关重要的,因为错误的使用会导致非常严重的并发问题。

SqlSessionFactoryBuilder:

一旦创建了SqlSessionFactory,就不再需要它了
局部变量
SqlSessionFactory:

说白了就可以想象为:数据库连接池
SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建一个实例。
因此SqlSessionFactory的最佳作用域是应用作用域(ApplocationContext)。
最简单的就是使用单例模式或静态单例模式。
SqlSession:

连接到连接池的一个请求
SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
用完之后需要赶紧关闭,否则资源被占用!

 

8、使用注解开发
8.1 面向接口开发
三个面向区别

面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性和方法;
面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现;
接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题,更多的体现就是对系统整体的架构;
8.2 使用注解开发
注解在接口上实现

@Select("select * from user")
List<User> getUsers();

需要在核心配置文件中绑定接口

<mappers>
<mapper class="com.kuang.dao.UserMapper"/>
</mappers>

增删改查

1 package com.bupt.dao;
2
3 import com.bupt.pojo.User;
4 import org.apache.ibatis.annotations.*;
5
6 import java.util.List;
7 import java.util.Map;
8
9 public interface UserDao {
10
11 User getUserById(int id);
12 List<User> getUserAll(Map<String,Integer> map);
13
14 @Select("select * from user")
15 List<User> getUsers();
16
17 @Delete("delete from user where id=#{uid}")
18 int deleteUser(@Param("uid") int id);
19
20 @Insert("insert into user(id,username) values(#{id},#{username})")
21 int insertUser(User user);
22
23 @Update("update user set username=#{username} where id=#{id}")
24 int update(User user);
25
26 }

对于增删改需要把opensession的参数设置为true,这样就等价于commit操作了,否则无法commit,及时写了commit,

public static SqlSession getSqlSession(){
SqlSession sqlSession = build.openSession(true);
return sqlSession;
}

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 import com.bupt.dao.UserDao;
2 import com.bupt.pojo.User;
3 import com.bupt.utils.MybatisUtils;
4 import javafx.geometry.VPos;
5 import org.apache.ibatis.session.SqlSession;
6 import org.junit.Test;
7
8 import java.util.HashMap;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.logging.Logger;
12
13 public class TestGetUserById {
14
15 @Test
16 public void test01(){
17 Logger logger = Logger.getLogger(String.valueOf(UserDao.class));
18 logger.info("info: 测试log4j");
19 SqlSession sqlSession = MybatisUtils.getSqlSession();
20 UserDao mapper = sqlSession.getMapper(UserDao.class);
21 User userById = mapper.getUserById(1);
22 System.out.println(userById);
23 sqlSession.close();
24 }
25
26 @Test
27 public void test02(){
28 SqlSession sqlSession = MybatisUtils.getSqlSession();
29 UserDao mapper = sqlSession.getMapper(UserDao.class);
30 HashMap<String, Integer> stringHashMap = new HashMap<String, Integer>();
31 stringHashMap.put("startIndex",1);
32 stringHashMap.put("pagesize",2);
33 List<User> userAll = mapper.getUserAll(stringHashMap);
34 for (User user:userAll){
35 System.out.println(user);
36 }
37 sqlSession.close();
38 }
39
40 @Test
41 public void test03(){
42 SqlSession sqlSession = MybatisUtils.getSqlSession();
43 UserDao mapper = sqlSession.getMapper(UserDao.class);
44 List<User> users = mapper.getUsers();
45 for (User user:users){
46 System.out.println(user);
47 }
48 sqlSession.close();
49 }
50
51 @Test
52 public void test04(){
53 SqlSession sqlSession = MybatisUtils.getSqlSession();
54 UserDao mapper = sqlSession.getMapper(UserDao.class);
55 int i = mapper.deleteUser(2);
56 System.out.println(i);
57 sqlSession.close();
58 }
59 @Test
60 public void test05(){
61 SqlSession sqlSession = MybatisUtils.getSqlSession();
62 UserDao mapper = sqlSession.getMapper(UserDao.class);
63 int i = mapper.insertUser(new User(3,"test"));
64 System.out.println(i);
65 sqlSession.close();
66 }
67
68 @Test
69 public void test06(){
70 SqlSession sqlSession = MybatisUtils.getSqlSession();
71 UserDao mapper = sqlSession.getMapper(UserDao.class);
72 int i = mapper.update(new User(3,"test02"));
73 System.out.println(i);
74 sqlSession.close();
75 }
76 }

View Code

测试

本质:反射机制实现

底层:动态代理

MyBatis详细执行流程

8.3 注解CURD
//方法存在多个参数,所有的参数前面必须加上@Param("id")注解
@Delete("delete from user where id = ${uid}")
int deleteUser(@Param("uid") int id);
关于@Param( )注解

基本类型的参数或者String类型,需要加上
引用类型不需要加
如果只有一个基本类型的话,可以忽略,但是建议大家都加上
我们在SQL中引用的就是我们这里的@Param()中设定的属性名
#{} 和 ${}

9、Lombok
Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码。仅五个字符(@Data)就可以替换数百行代码从而产生干净,简洁且易于维护的Java类。

使用步骤:

在IDEA中安装Lombok插件

在项目中导入lombok的jar包

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>

 

在程序上加注解

1 @Getter and @Setter
2 @FieldNameConstants
3 @ToString
4 @EqualsAndHashCode
5 @AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
6 @Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
7 @Data
8 @Builder
9 @SuperBuilder
10 @Singular
11 @Delegate
12 @Value
13 @Accessors
14 @Wither
15 @With
16 @SneakyThrows
17 @val

说明:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String password;
}

 对于mybatis来说复杂的sql语句还是用配置文件来做,下面两个点是多对一一对多的介绍。推荐使用联合嵌套查询

 

10、多对一处理

多个学生一个老师;

数据库表

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 CREATE TABLE `teacher` (
2 `id` INT(10) NOT NULL,
3 `name` VARCHAR(30) DEFAULT NULL,
4 PRIMARY KEY (`id`)
5 ) ENGINE=INNODB DEFAULT CHARSET=utf8
6
7 INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师');
8
9 CREATE TABLE `student` (
10 `id` INT(10) NOT NULL,
11 `name` VARCHAR(30) DEFAULT NULL,
12 `tid` INT(10) DEFAULT NULL,
13 PRIMARY KEY (`id`),
14 KEY `fktid` (`tid`),
15 CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
16 ) ENGINE=INNODB DEFAULT CHARSET=utf8INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
17 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1');
18 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1');
19 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1');
20 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');

View Code

1. 测试环境搭建

  1. 导入lombok
  2. 新建实体类Teacher,Student
  3. 建立Mapper接口
  4. 建立Mapper.xml文件
  5. 在核心配置文件中绑定注册我们的Mapper接口或者文件 【方式很多,随心选】
  6. 测试查询是否能够成功

具体过程为

先在maven里面添加依赖

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1     <dependencies>
2 <dependency>
3 <groupId>org.projectlombok</groupId>
4 <artifactId>lombok</artifactId>
5 <version>1.18.16</version>
6 </dependency>
7 <dependency>
8 <groupId>junit</groupId>
9 <artifactId>junit</artifactId>
10 <version>4.13</version>
11 <scope>test</scope>
12 </dependency>
13 <dependency>
14 <groupId>mysql</groupId>
15 <artifactId>mysql-connector-java</artifactId>
16 <version>8.0.15</version>
17 </dependency>
18 <dependency>
19 <groupId>org.mybatis</groupId>
20 <artifactId>mybatis</artifactId>
21 <version>3.5.4</version>
22 </dependency>
23 <dependency>
24 <groupId>log4j</groupId>
25 <artifactId>log4j</artifactId>
26 <version>1.2.12</version>
27 </dependency>
28
29 </dependencies>

View Code

配置文件

db.properties

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 driver=com.mysql.cj.jdbc.Driver
2 url=jdbc:mysql://localhost:3306/student?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
3 username=root
4 password=root

View Code

log4j.properties

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
2 log4j.rootLogger=DEBUG,console,file
3 #控制台输出的相关设置
4 log4j.appender.console = org.apache.log4j.ConsoleAppender
5 log4j.appender.console.Target = System.out
6 log4j.appender.console.Threshold=DEBUG
7 log4j.appender.console.layout = org.apache.log4j.PatternLayout
8 log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
9 #文件输出的相关设置
10 log4j.appender.file = org.apache.log4j.RollingFileAppender
11 log4j.appender.file.File=./log/rzp.log
12 log4j.appender.file.MaxFileSize=10mb
13 log4j.appender.file.Threshold=DEBUG
14 log4j.appender.file.layout=org.apache.log4j.PatternLayout
15 log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
16 #日志输出级别
17 log4j.logger.org.mybatis=DEBUG
18 log4j.logger.java.sql=DEBUG
19 log4j.logger.java.sql.Statement=DEBUG
20 log4j.logger.java.sql.ResultSet=DEBUG
21 log4j.logger.java.sq1.PreparedStatement=DEBUG

View Code

mybatis-config.xml

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE configuration
3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
5 <!--configuration核心配置文件-->
6 <configuration>
7 <properties resource="db.properties"/>
8 <!-- <settings>-->
9 <!--<!&ndash; <setting name="logImpl" value="log4j"/>&ndash;>-->
10 <!-- </settings>-->
11 <typeAliases>
12 <typeAlias type="com.bupt.pojo.Teacher" alias="Teacher"/>
13 <typeAlias type="com.bupt.pojo.Student" alias="Student"/>
14 <typeAlias type="com.bupt.pojo.Student2" alias="Student2"/>
15 <typeAlias type="com.bupt.pojo.Teacher2" alias="Teacher2"/>
16 </typeAliases>
17 <environments default="development">
18 <environment id="development">
19 <transactionManager type="JDBC"></transactionManager>
20 <dataSource type="POOLED">
21 <property name="driver" value="${driver}"/>
22 <property name="url" value="${url}"/>
23 <property name="username" value="${username}"/>
24 <property name="password" value="${password}"/>
25 </dataSource>
26 </environment>
27 </environments>
28
29 <!-- 无论使用包扫描(package)还是使用class方法要注意一下
30 (1)接口和他的Mapper配置文件必须同名
31 (2)接口和他的Mapper配置文件必须在同一个包里面
32 -->
33 <!-- <mappers>-->
34 <!-- <mapper resource="com/bupt/dao/StudentMapper.xml"/>-->
35 <!-- <mapper class="com.bupt.dao.TeacherMapper"/>-->
36 <!-- </mappers>-->
37
38 <mappers>
39 <package name="com.bupt.dao"/>
40 </mappers>
41 </configuration>

View Code

utils包下的MybatisUtils文件

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 package com.bupt.utils;
2
3 import org.apache.ibatis.io.Resources;
4 import org.apache.ibatis.session.SqlSession;
5 import org.apache.ibatis.session.SqlSessionFactory;
6 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
7
8 import java.io.IOException;
9 import java.io.InputStream;
10
11 public class MybatisUtils {
12 static InputStream resourceAsStream = null;
13 static SqlSessionFactory build = null;
14 static {
15
16 try {
17 String resource = "mybatis-config.xml";
18 resourceAsStream = Resources.getResourceAsStream(resource);
19 build = new SqlSessionFactoryBuilder().build(resourceAsStream);
20 } catch (IOException e) {
21 e.printStackTrace();
22 }
23 }
24
25 public static SqlSession getSqlSession(){
26 SqlSession sqlSession = build.openSession();
27 return sqlSession;
28 }
29 }

View Code

实体类Student和Teacher

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

package com.bupt.pojo;

import lombok.Data;

@Data
public class Student {
private int id;
private String name;
private Teacher teacher;
}

Student

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 package com.bupt.pojo;
2
3 import lombok.Data;
4
5 @Data
6 public class Teacher {
7 private int id;
8 private String name;
9 }

Teacher

Mapper接口和对应的配置文件

StudentMapper

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 package com.bupt.dao;
2
3 import com.bupt.pojo.Student;
4
5 import java.util.List;
6
7 public interface StudentMapper {
8 //查询所有学生的信息,及其对应的老师的信息
9 public List<Student> getStudent();
10 public List<Student> getStudent2();
11 }

View Code

StudentMapper.xm;

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper
3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5 <mapper namespace="com.bupt.dao.StudentMapper">
6
7 <select id="getStudent2" resultMap="StudentTeacher2">
8 select s.id, s.name, t.name tname
9 from student s,teacher t
10 where s.tid = t.id
11 </select>
12 <resultMap id="StudentTeacher2" type="Student">
13 <result property="id" column="id"/>
14 <result property="name" column="name"/>
15 <association property="teacher" javaType="Teacher" >
16 <result property="name" column="tname"/>
17 </association>
18 </resultMap>
19
20
21 <!-- 方式一 按照子查询的方式 -->
22 <select id="getStudent" resultMap="StudentTeacher">
23 select * from student;
24 </select>
25
26 <resultMap id="StudentTeacher" type="Student">
27 <result property="id" column="id"/>
28 <result property="name" column="name"/>
29 <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
30 </resultMap>
31
32 <select id="getTeacher" resultType="Teacher">
33 select * from teacher where id=#{tid}
34 </select>
35 </mapper>

View Code

TeacherMapper

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 package com.bupt.dao;
2
3 import com.bupt.pojo.Teacher;
4 import org.apache.ibatis.annotations.Param;
5 import org.apache.ibatis.annotations.Select;
6
7 public interface TeacherMapper {
8
9 @Select("select * from teacher where id=#{id}")
10 Teacher getTeacher(@Param("id") int id);
11 }

View Code

TeacherMapper.xml

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper
3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5 <mapper namespace="com.bupt.dao.TeacherMapper">
6
7 </mapper>

View Code

测试

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1     @Test
2 public void test01(){
3 SqlSession sqlSession = MybatisUtils.getSqlSession();
4 TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
5 Teacher teacher = mapper.getTeacher(1);
6 System.out.println(teacher);
7 sqlSession.close();
8 }
9
10 @Test
11 public void test02(){
12 SqlSession sqlSession = MybatisUtils.getSqlSession();
13 StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
14 for (Student student : mapper.getStudent()) {
15 System.out.println(student);
16 }
17 sqlSession.close();
18 }
19
20 @Test
21 public void test03(){
22 SqlSession sqlSession = MybatisUtils.getSqlSession();
23 StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
24 for (Student student : mapper.getStudent2()) {
25 System.out.println(student);
26 }
27 sqlSession.close();
28 }

View Code

其中最重要的就是两种处理方式

方式一:按照查询嵌套处理

<!--
思路:
1. 查询所有的学生信息
2. 根据查询出来的学生的tid寻找特定的老师 (子查询)
-->
<select id="getStudent" resultMap="StudentTeacher">
select * from student
</select>
<resultMap id="StudentTeacher" type="student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性,我们需要单独出来 对象:association 集合:collection-->
<collection property="teacher" column="tid" javaType="teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="teacher">
select * from teacher where id = #{id}
</select>

方式二:按照结果嵌套处理

1     <!--按照结果进行查询-->
2 <select id="getStudent2" resultMap="StudentTeacher2">
3 select s.id sid , s.name sname, t.name tname
4 from student s,teacher t
5 where s.tid=t.id
6 </select>
7 <!--结果封装,将查询出来的列封装到对象属性中-->
8 <resultMap id="StudentTeacher2" type="student">
9 <result property="id" column="sid"/>
10 <result property="name" column="sname"/>
11 <association property="teacher" javaType="teacher">
12 <result property="name" column="tname"></result>
13 </association>
14 </resultMap>

回顾Mysql多对一查询方式:

  • 子查询 (按照查询嵌套)
  • 联表查询 (按照结果嵌套)

11、一对多处理

一个老师多个学生;

对于老师而言,就是一对多的关系;

1. 环境搭建

实体类

1 @Data
2 public class Student {
3 private int id;
4 private String name;
5 private int tid;
6 }
1 @Data
2 public class Teacher {
3 private int id;
4 private String name;
5
6 //一个老师拥有多个学生
7 private List<Student> students;
8 }

2. 按照结果嵌套嵌套处理(推荐使用的查询方式)

1 <!--按结果嵌套查询-->
2 <select id="getTeacher" resultMap="StudentTeacher">
3 SELECT s.id sid, s.name sname,t.name tname,t.id tid FROM student s, teacher t
4 WHERE s.tid = t.id AND tid = #{tid}
5 </select>
6 <resultMap id="StudentTeacher" type="Teacher">
7 <result property="id" column="tid"/>
8 <result property="name" column="tname"/>
9 <!--复杂的属性,我们需要单独处理 对象:association 集合:collection
10 javaType=""指定属性的类型!
11 集合中的泛型信息,我们使用ofType获取
12 -->
13 <collection property="students" ofType="Student">
14 <result property="id" column="sid"/>
15 <result property="name" column="sname"/>
16 <result property="tid" column="tid"/>
17 </collection>
18 </resultMap>

子查询方式实现一对多

1     <select id="getTeacher2" resultMap="TeacherStudent2">
2 select * from teacher where id=#{tid}
3 </select>
4 <resultMap id="TeacherStudent2" type="Teacher2">
5 <collection property="student" javaType="ArrayList" ofType="Student2" select="getTeacherStudent2" column="id"/>
6 </resultMap>
7 <select id="getTeacherStudent2" resultType="Student2">
8 select *
9 from student where tid = #{tid};
10 </select>

小结
关联 - association 【多对一】
集合 - collection 【一对多】
javaType & ofType
JavaType用来指定实体类中的类型
ofType用来指定映射到List或者集合中的pojo类型,泛型中的约束类型
注意点:

  • 保证SQL的可读性,尽量保证通俗易懂
  • 注意一对多和多对一,属性名和字段的问题
  • 如果问题不好排查错误,可以使用日志,建议使用Log4j

面试高频

  • Mysql引擎
  • InnoDB底层原理
  • 索引
  • 索引优化

12、动态SQL
什么是动态SQL:动态SQL就是根据不同的条件生成不同的SQL语句

所谓的动态SQL,本质上还是SQL语句,只是我们可以在SQL层面,去执行一个逻辑代码


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


搭建环境

CREATE TABLE `mybatis`.`blog`  (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '博客id',
`title` varchar(30) NOT NULL COMMENT '博客标题',
`author` varchar(30) NOT NULL COMMENT '博客作者',
`create_time` datetime(0) NOT NULL COMMENT '创建时间',
`views` int(30) NOT NULL COMMENT '浏览量',
PRIMARY KEY (`id`)
)

创建一个基础工程

导包

编写配置文件

编写实体类

1 @Data
2 public class Blog {
3 private int id;
4 private String title;
5 private String author;
6
7 private Date createTime;// 属性名和字段名不一致
8 private int views;
9 }

BlogMapper

狂神说Java Mybatis笔记_sql狂神说Java Mybatis笔记_sql_02

1 package com.bupt.dao;
2
3 import com.bupt.pojo.Blog;
4
5 import java.util.List;
6 import java.util.Map;
7
8 public interface BlogMapper {
9
10 int addBook(Blog blog);
11
12 List<Blog> queryBlogIf(Map map);
13
14 List<Blog> queryChoose(Map map);
15
16 //更新博客
17 int updateBlog(Map map);
18 }

View Code

BlogMapper.xml

通过使用动态sql可以动态的编写sql语句,并且动态sql可以自动去除多余的and和where和,等多余的内容。

1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper
3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5 <mapper namespace="com.bupt.dao.BlogMapper">
6
7 <insert id="addBook" parameterType="blog">
8 insert into blog(id,title,author,create_time,views) values (#{id},#{title},#{author},#{createTime},#{views});
9 </insert>
10
11 <select id="queryBlogIf" parameterType="map" resultType="blog">
12 select * from blog
13 <where>
14 <if test="title != null">
15 title = #{title}
16 </if>
17 <if test="author != null">
18 and author = #{author}
19 </if>
20 </where>
21 </select>
22
23 <select id="queryChoose" parameterType="map" resultType="blog">
24 select * from blog
25 <where>
26 <choose>
27 <when test="title != null">
28 title = #{title}
29 </when>
30 <when test="author !=null">
31 and author = #{author}
32 </when>
33 <otherwise>
34 and view = #{views}
35 </otherwise>
36 </choose>
37 </where>
38 </select>
39
40 <update id="updateBlog" parameterType="map">
41 update blog
42 <set>
43 <if test="title != null">
44 title = #{title},
45 </if>
46 <if test="author != null">
47 author = #{author}
48 </if>
49 </set>
50 where id = #{id}
51 </update>
52
53
54 </mapper>

SQL片段
有的时候,我们可能会将一些功能的部分抽取出来,方便服用!

使用SQL标签抽取公共部分可

<sql id="if-title-author">
<if test="title!=null">
title = #{title}
</if>
<if test="author!=null">
and author = #{author}
</if>
</sql>

在需要使用的地方使用Include标签引用即可

<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from blog
<where>
<include refid="if-title-author"></include>
</where>
</select>

13、缓存
13.1 简介


查询 : 连接数据库,耗资源

一次查询的结果,给他暂存一个可以直接取到的地方 --> 内存:缓存

我们再次查询的相同数据的时候,直接走缓存,不走数据库了


什么是缓存[Cache]?

  • 存在内存中的临时数据。
  • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题

为什么使用缓存?

  • 减少和数据库的交互次数,减少系统开销,提高系统效率

什么样的数据可以使用缓存?

  • 经常查询并且不经常改变的数据 【可以使用缓存】

13.2 MyBatis缓存

  • MyBatis包含一个非常强大的查询缓存特性,它可以非常方便的定制和配置缓存,缓存可以极大的提高查询效率。
  • MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存
  • 默认情况下,只有一级缓存开启(SqlSession级别的缓存,也称为本地缓存)
  • 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
  • 为了提高可扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来定义二级缓存。

13.3 一级缓存
一级缓存也叫本地缓存:SqlSession
与数据库同一次会话期间查询到的数据会放在本地缓存中
以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库
测试步骤:

开启日志

测试在一个Session中查询两次记录

@Test
public void test1() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserById(1);
System.out.println(user);

System.out.println("=====================================");

User user2 = mapper.getUserById(1);
System.out.println(user2 == user);
}

发现只进行了一次数据库连接

狂神说Java Mybatis笔记_java_63

 

 

缓存失效的情况:

  1. 查询不同的东西
  2. 增删改操作,可能会改变原来的数据,所以必定会刷新缓存
  3. 查询不同的Mapper.xml
  4. 手动清理缓存
sqlSession.clearCache();

 

13.4 二级缓存

  • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
  • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存
  • 工作机制
  • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中
  • 如果会话关闭了,这个会员对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中
  • 新的会话查询信息,就可以从二级缓存中获取内容
  • 不同的mapper查询出的数据会放在自己对应的缓存(map)中
  • 一级缓存开启(SqlSession级别的缓存,也称为本地缓存)

 

二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
为了提高可扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来定义二级缓存。
步骤:

 

开启全局缓存

 

<!--显示的开启全局缓存,默认也是开启的,所以可以不写,但是写上其实是起到提醒的作用-->
<setting name="cacheEnabled" value="true"/>
在Mapper.xml中使用缓存

 

<!--在当前Mapper.xml中使用二级缓存-->
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>

 

  1. 测试
  1. 问题:我们需要将实体类序列化,否则就会报错

 

小结:

 

  • 只要开启了二级缓存,在同一个Mapper下就有效
  • 所有的数据都会放在一级缓存中
  • 只有当前会话提交,或者关闭的时候,才会提交到二级缓存中

 

13.5 缓存原理

 

狂神说Java Mybatis笔记_sql_64

 

 

注意:

 

只有查询才有缓存,根据数据是否需要缓存(修改是否频繁选择是否开启)useCache=“true”

 


<select id="getUserById" resultType="user" useCache="true"> select * from user where id = #{id} </select>


 

13.6 自定义缓存-ehcache
Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存

 

导包

 

<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>

在mapper中指定使用我们的ehcache缓存实现

 

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

 

作者:你的雷哥

本文版权归作者所有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。

举报

相关推荐

0 条评论