MyBatis 映射配置解析以及动态SQL配置案例

什么是 MyBatis ?

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

MyBatis的 Git 代码库

corp数据库全部表结构与数据

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
DROP DATABASE IF EXISTS `corp`;

CREATE DATABASE `corp`;

USE `corp`;

-- 部门
CREATE TABLE `depa` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`depa_name` NVARCHAR (50) NOT NULL
) ;

-- 职员
CREATE TABLE `emp` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`emp_name` NVARCHAR (50) NOT NULL,
`depa_id` INT NOT NULL
) ;

-- 职位
CREATE TABLE `post` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`post_name` NVARCHAR (50) NOT NULL
) ;

-- 职员职位
CREATE TABLE `emp_post` (
`emp_id` INT NOT NULL,
`post_id` INT NOT NULL
) ;

INSERT INTO `depa`(`depa_name`) VALUES('销售部');
INSERT INTO `depa`(`depa_name`) VALUES('美工部');

INSERT INTO `emp`(`emp_name`,`depa_id`) VALUES('张三',2);
INSERT INTO `emp`(`emp_name`,`depa_id`) VALUES('李四',1);
INSERT INTO `emp`(`emp_name`,`depa_id`) VALUES('王五',1);
INSERT INTO `emp`(`emp_name`,`depa_id`) VALUES('赵六',1);

INSERT INTO `post`(`post_name`) VALUES('职员');
INSERT INTO `post`(`post_name`) VALUES('主管');
INSERT INTO `post`(`post_name`) VALUES('经理');
INSERT INTO `post`(`post_name`) VALUES('部门经理');

INSERT INTO `emp_post`(`emp_id`,`post_id`) VALUES(1,1);
INSERT INTO `emp_post`(`emp_id`,`post_id`) VALUES(2,2);
INSERT INTO `emp_post`(`emp_id`,`post_id`) VALUES(3,3);
INSERT INTO `emp_post`(`emp_id`,`post_id`) VALUES(4,4);
INSERT INTO `emp_post`(`emp_id`,`post_id`) VALUES(1,4);

SELECT * FROM `depa`;
SELECT * FROM `emp`;
SELECT * FROM `post`;
SELECT * FROM `emp_post`;

DROP TABLE `depa`;
DROP TABLE `emp`;
DROP TABLE `post`;
DROP TABLE `emp_post`;

pom.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com</groupId>
<artifactId>Corp</artifactId>
<version>1.0-SNAPSHOT</version>

<dependencies>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
</dependencies>
</project>

MybatisUtil Mybatis工具类

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
package com.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MybatisUtil {
private static SqlSessionFactory sessionFactory;

static {
try {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}

public static SqlSession getSession() {
return sessionFactory.openSession(false);//true为自动提交事务
}
}

Depa 部门实体类

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
package com.entity;

import java.util.ArrayList;
import java.util.List;

public class Depa {
private Integer id;
private String depa_name;
private List<Emp> emps = new ArrayList<Emp>();

@Override
public String toString() {
return "Depa{" +
"id=" + id +
", depa_name='" + depa_name + '\'' +
", emps=" + emps +
'}';
}

public Integer getId() {
return id;
}

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

public String getDepa_name() {
return depa_name;
}

public void setDepa_name(String depa_name) {
this.depa_name = depa_name;
}

public List<Emp> getEmps() {
return emps;
}

public void setEmps(List<Emp> emps) {
this.emps = emps;
}
}

对应 Depa 部门实体类 的实现接口 DepaDao 接口类

1
2
3
4
5
6
7
8
9
package com.dao;

import com.entity.Depa;

import java.util.List;

public interface DepaDao {
List<Depa> getAll();
}

对应 Depa 部门实体类 的映射配置文件 DepaMapper.xml

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
<?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 mapper接口 必填 随便填值 防止SQL语句ID重名-->
<mapper namespace="com.dao.DepaDao">
<!--<insert id=""></insert>-->
<!--<delete id=""></delete>-->
<!--<update id=""></update>-->
<!--resultType 返回类型 实体类全限定类名-->
<select id="getAll" resultMap="DepaMapper">
SELECT *,e.`id` eId,d.`id` dId FROM depa d
INNER JOIN emp e ON d.`id`=e.`depa_id`
</select>

<!--type 为resultMap返回类型-->
<resultMap id="DepaMapper" type="Depa">
<!--column 为数据库查到后取的别名 property 为type对象对应属性名-->
<result column="dId" property="id"/>

<!--因为数据库的字段与实体类属性名一致-->
<!--所以在 mybatis-config.xml 配置 <setting name="autoMappingBehavior" value="FULL"/>-->
<!--达到 自动映射行为 : 局部的PARTIAL 重复的 <result/> 可以省略-->
<!--<result column="" property=""/>-->

<!--收集 一对多-->
<!--property 为type对象对应属性名 javaType 为所属类型-->
<collection property="emps" javaType="Emp">
<!--column 为数据库查到后取的别名 property 为javaType对象对应属性名-->
<result column="" property=""/>
<!--因为数据库的字段与实体类属性名一致-->
<!--所以在 mybatis-config.xml 配置 <setting name="autoMappingBehavior" value="FULL"/>-->
<!--达到 自动映射行为 : 全部FULL 重复的 <result/> 可以省略-->
<result column="eId" property="id"/>
</collection>
</resultMap>
</mapper>

Emp 职员实体类

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
package com.entity;

import java.util.ArrayList;
import java.util.List;

public class Emp {
private Integer id;
private String emp_name;
private Depa depa_id;
private List<Post> posts = new ArrayList<Post>();

@Override
public String toString() {
return "Emp{" +
"id=" + id +
", emp_name='" + emp_name + '\'' +
", depa_id=" + depa_id +
", posts=" + posts +
'}';
}

public Integer getId() {
return id;
}

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

public String getEmp_name() {
return emp_name;
}

public void setEmp_name(String emp_name) {
this.emp_name = emp_name;
}

public Depa getDepa_id() {
return depa_id;
}

public void setDepa_id(Depa depa_id) {
this.depa_id = depa_id;
}

public List<Post> getPosts() {
return posts;
}

public void setPosts(List<Post> posts) {
this.posts = posts;
}
}

对应 Emp 职员实体类 的实现接口 EmpDao 接口类

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

import com.entity.Emp;

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

public interface EmpDao {
List<Emp> getAll();

Integer saveOrUpdate(Emp emp);

Integer del(Integer[] idArray);

List<Emp> getByNames(List names);

List<Emp> getByIdAndNames(Map map);
}

对应 Emp 职员实体类 的映射配置文件 EmpMapper.xml

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
<?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 mapper接口 必填 随便填值 防止SQL语句ID重名-->
<mapper namespace="com.dao.EmpDao">
<!--
<where> 自动删除第一个 and 或者 or
item 表示集合中每一个元素进行迭代时的别名
open 表示该语句以什么开始
separator 表示在每次进行迭代之间以什么符号作为分隔符
close表示以什么结束
如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
如果传入的参数是多个的时候,就需要把它们封装成一个Map map的key就是参数名-->
<delete id="del">
DELETE FROM emp
<where>
<foreach collection="array" item="eId">
OR id = #{eId}
</foreach>
</where>
</delete>

<!--<set> 自动去除最后的逗号 , -->
<update id="saveOrUpdate">
<if test="null != id">
UPDATE emp
<set>
<if test="null != emp_name">
emp_name = #{emp_name},
</if>
<if test="null != depa_id and null != depa_id.id">
depa_id = #{depa_id.id},
</if>
</set>
where id = #{id}
</if>
<if test="null == id">
INSERT INTO `emp`(`emp_name`,`depa_id`) VALUES(#{emp_name},#{depa_id.id})
</if>
</update>
<!--resultType 返回类型 实体类全限定类名-->
<select id="getAll" resultMap="EmpMapper">
SELECT * FROM emp e
INNER JOIN depa d ON d.`id`=e.`depa_id`
INNER JOIN emp_post ep ON ep.`emp_id`=e.`id`
INNER JOIN post p ON p.`id`=ep.`post_id`
</select>

<!--
prefix 前缀添加什么
prefixOverrides 前缀移除什么 || 为或者
suffix 后缀添加什么
suffixOverrides 后缀移除什么 || 为或者
<trim prefix="WHERE" prefixOverrides="OR || AND"> 等价 <where>-->
<select id="getByNames" resultMap="EmpMapper">
SELECT * FROM emp e
INNER JOIN depa d ON d.`id`=e.`depa_id`
INNER JOIN emp_post ep ON ep.`emp_id`=e.`id`
INNER JOIN post p ON p.`id`=ep.`post_id`
<trim prefix="WHERE" prefixOverrides="OR || AND">
<foreach collection="list" item="name">
OR e.`emp_name` LIKE CONCAT('%',#{name},'%')
</foreach>
</trim>
</select>

<!--
prefix 前缀添加什么
prefixOverrides 前缀移除什么 || 为或者
suffix 后缀添加什么
suffixOverrides 后缀移除什么 || 为或者
<trim prefix="WHERE" prefixOverrides="OR || AND"> 等价 <where>-->
<select id="getByIdAndNames" resultMap="EmpMapper">
SELECT * FROM emp e
INNER JOIN depa d ON d.`id`=e.`depa_id`
INNER JOIN emp_post ep ON ep.`emp_id`=e.`id`
INNER JOIN post p ON p.`id`=ep.`post_id`
<trim prefix="WHERE" prefixOverrides="OR|AND">
AND e.`id` = #{mapIdName} AND
</trim>
<trim prefixOverrides="OR|AND">
e.`emp_name` IN
<foreach collection="mapNameList" item="name" open="(" separator="," close=")">
#{name}
</foreach>
</trim>
</select>


<!--type 为resultMap返回类型-->
<resultMap id="EmpMapper" type="Emp">
<!--column 为数据库查到后取的别名 property 为type对象对应属性名-->
<result column="emp_id" property="id"/>

<!--因为数据库的字段与实体类属性名一致-->
<!--所以在 mybatis-config.xml 配置 <setting name="autoMappingBehavior" value="FULL"/>-->
<!--达到 自动映射行为 : 局部的PARTIAL 重复的 <result/> 可以省略-->
<!--<result column="" property=""/>-->

<!--联合查询 一对一-->
<!--property 为type对象对应属性名 javaType 为所属类型-->
<association property="depa_id" javaType="Depa">
<!--column 为数据库查到后取的别名 property 为javaType对象对应属性名-->
<result column="depa_id" property="id"/>
<!--因为数据库的字段与实体类属性名一致-->
<!--所以在 mybatis-config.xml 配置 <setting name="autoMappingBehavior" value="FULL"/>-->
<!--达到 自动映射行为 : 全部FULL 重复的 <result/> 可以省略-->
<!--<result column="" property=""/>-->
</association>

<!--收集 一对多-->
<!--property 为type对象对应属性名 javaType 为所属类型-->
<collection property="posts" javaType="Post">
<!--column 为数据库查到后取的别名 property 为javaType对象对应属性名-->
<result column="post_id" property="id"/>
<!--因为数据库的字段与实体类属性名一致-->
<!--所以在 mybatis-config.xml 配置 <setting name="autoMappingBehavior" value="FULL"/>-->
<!--达到 自动映射行为 : 全部FULL 重复的 <result/> 可以省略-->
<!--<result column="" property=""/>-->
</collection>
</resultMap>
</mapper>

Post 职位实体类

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
package com.entity;

import java.util.ArrayList;
import java.util.List;

public class Post {
private Integer id;
private String post_name;
private List<Emp> emps = new ArrayList<Emp>();

@Override
public String toString() {
return "Post{" +
"id=" + id +
", post_name='" + post_name + '\'' +
", emps=" + emps +
'}';
}

public Integer getId() {
return id;
}

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

public String getPost_name() {
return post_name;
}

public void setPost_name(String post_name) {
this.post_name = post_name;
}

public List<Emp> getEmps() {
return emps;
}

public void setEmps(List<Emp> emps) {
this.emps = emps;
}
}

对应 Post 职位实体类 的实现接口 PostDao 接口类

1
2
3
4
5
6
7
8
9
package com.dao;

import com.entity.Post;

import java.util.List;

public interface PostDao {
List<Post> getAll();
}

对应 Post 职位实体类 的映射配置文件 PostMapper.xml

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
<?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 mapper接口 必填 随便填值 防止SQL语句ID重名-->
<mapper namespace="com.dao.PostDao">
<!--resultType 返回类型 实体类全限定类名-->
<select id="getAll" resultMap="PostMapper">
SELECT * FROM post p
INNER JOIN emp_post ep ON ep.`post_id`=p.`id`
INNER JOIN emp e ON e.`id`=ep.`emp_id`
INNER JOIN depa d ON d.`id`=e.`depa_id`
</select>

<!--type 为resultMap返回类型-->
<resultMap id="PostMapper" type="Post">
<!--column 为数据库查到后取的别名 property 为type对象对应属性名-->
<result column="post_id" property="id"/>

<!--因为数据库的字段与实体类属性名一致-->
<!--所以在 mybatis-config.xml 配置 <setting name="autoMappingBehavior" value="FULL"/>-->
<!--达到 自动映射行为 : 局部的PARTIAL 重复的 <result/> 可以省略-->
<!--<result column="" property=""/>-->

<!--联合查询 一对一-->
<!--property 为type对象对应属性名 javaType 为所属类型-->
<association property="emps" javaType="Emp">
<!--column 为数据库查到后取的别名 property 为javaType对象对应属性名-->
<result column="emp_id" property="id"/>
<!--因为数据库的字段与实体类属性名一致-->
<!--所以在 mybatis-config.xml 配置 <setting name="autoMappingBehavior" value="FULL"/>-->
<!--达到 自动映射行为 : 全部FULL 重复的 <result/> 可以省略-->
<!--<result column="" property=""/>-->

<association property="depa_id" javaType="Depa">
<!--column 为数据库查到后取的别名 property 为javaType对象对应属性名-->
<result column="depa_id" property="id"/>
<!--因为数据库的字段与实体类属性名一致-->
<!--所以在 mybatis-config.xml 配置 <setting name="autoMappingBehavior" value="FULL"/>-->
<!--达到 自动映射行为 : 全部FULL 重复的 <result/> 可以省略-->
<!--<result column="" property=""/>-->
</association>
</association>
</resultMap>
</mapper>

mybatis-config.xml MyBatis配置文件

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
<?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>
<!--可以配置在Java属性配置文件 *.properties 中-->
<properties resource="">
<!--可以配置键值对属性在这里而不用配置文件-->
<property name="" value=""/>
</properties>
<settings>
<!-- 打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!--达到 自动映射行为 : 全部FULL 局部的PARTIAL 禁止自动匹配NONE-->
<setting name="autoMappingBehavior" value="FULL"/>
</settings>
<!--为Java类型命名一个别名 alias 用于 mappers.xml 的 resultType 直接调用 不用写全限定类名-->
<typeAliases>
<!--为一个Java类型命名一个别名-->
<!--<typeAlias type="" alias=""/>-->
<!--为 com.entity 包 全部Java类型命名一个别名 别名为Java类名-->
<package name="com.entity"/>
</typeAliases>
<!--环境-->
<environments default="development">
<!--环境变量-->
<environment id="development">
<!--事务管理器-->
<transactionManager type="JDBC"></transactionManager>
<!--数据源-->
<dataSource type="POOLED">
<property name="username" value="root"/>
<property name="password" value="simon"/>
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--MySQL数据库-->
<property name="url" value="jdbc:mysql://localhost:3306/corp"/>
</dataSource>
</environment>
</environments>
<!--映射器-->
<mappers>
<!--实体类映射-->
<mapper resource="com/entity/DepaMapper.xml"/>
<mapper resource="com/entity/EmpMapper.xml"/>
<mapper resource="com/entity/PostMapper.xml"/>
</mappers>
</configuration>

Test 测试类

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
package com.test;

import com.dao.DepaDao;
import com.dao.EmpDao;
import com.dao.PostDao;
import com.entity.Depa;
import com.entity.Emp;
import com.entity.Post;
import com.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;

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

public class Test {
public static void main(String[] args) {
SqlSession session = MybatisUtil.getSession();
DepaDao depaDao = session.getMapper(DepaDao.class);
EmpDao empDao = session.getMapper(EmpDao.class);
PostDao postDao = session.getMapper(PostDao.class);

List<Depa> depaDaoAll = depaDao.getAll();
for (Depa depa : depaDaoAll) {
System.out.println(depa);
}

System.out.println("getByNames------三 || 四");
List<Emp> byNames = empDao.getByNames(Arrays.asList("三", "四"));
for (Emp emp : byNames) {
System.out.println(emp);
}

Map<String, Object> map = new HashMap<String, Object>();
map.put("mapIdName", 2);
map.put("mapNameList", Arrays.asList("张三", "李四", "王五"));
List<Emp> byIdAndNames = empDao.getByIdAndNames(map);
System.out.println("byIdAndNames------" + map);
for (Emp emp : byIdAndNames) {
System.out.println(emp);
}


Emp simon = new Emp();
simon.setId(1);
simon.setEmp_name("Simon");
Depa depa = new Depa();
depa.setId(1);
simon.setDepa_id(depa);
if (0 == empDao.saveOrUpdate(simon))
System.out.println("saveOrUpdate-----false");
else
System.out.println("saveOrUpdate-----true");


Integer del = empDao.del(new Integer[]{2, 3});
if (0 == del)
System.out.println("del-----false");
else
System.out.println("del-----true");
System.out.println("del-----" + del);


List<Emp> empDaoAll = empDao.getAll();
for (Emp emp : empDaoAll) {
System.out.println(emp);
}


List<Post> postDaoAll = postDao.getAll();
for (Post post : postDaoAll) {
System.out.println(post);
}

}
}

控制台输出结果

mybatis-config.xml 配置 <setting name="logImpl" value="STDOUT_LOGGING"/> 控制台会打印执行的SQL语句以及得到的参数

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
==>  Preparing: SELECT *,e.`id` eId,d.`id` dId FROM depa d INNER JOIN emp e ON d.`id`=e.`depa_id`
==> Parameters:
<== Columns: id, depa_name, id, emp_name, depa_id, eId, dId
<== Row: 1, 销售部, 2, 李四, 1, 2, 1
<== Row: 1, 销售部, 3, 王五, 1, 3, 1
<== Row: 1, 销售部, 4, 赵六, 1, 4, 1
<== Row: 2, 美工部, 1, 张三, 2, 1, 2
<== Total: 4
Depa{id=1, depa_name='销售部', emps=[Emp{id=2, emp_name='李四', depa_id=null, posts=[]}, Emp{id=3, emp_name='王五', depa_id=null, posts=[]}, Emp{id=4, emp_name='赵六', depa_id=null, posts=[]}]}
Depa{id=2, depa_name='美工部', emps=[Emp{id=1, emp_name='张三', depa_id=null, posts=[]}]}
getByNames------三 || 四
==> Preparing: SELECT * FROM emp e INNER JOIN depa d ON d.`id`=e.`depa_id` INNER JOIN emp_post ep ON ep.`emp_id`=e.`id` INNER JOIN post p ON p.`id`=ep.`post_id` WHERE e.`emp_name` LIKE CONCAT('%',?,'%') OR e.`emp_name` LIKE CONCAT('%',?,'%')
==> Parameters: 三(String), 四(String)
<== Columns: id, emp_name, depa_id, id, depa_name, emp_id, post_id, id, post_name
<== Row: 1, 张三, 2, 2, 美工部, 1, 1, 1, 职员
<== Row: 2, 李四, 1, 1, 销售部, 2, 2, 2, 主管
<== Row: 1, 张三, 2, 2, 美工部, 1, 4, 4, 部门经理
<== Total: 3
Emp{id=1, emp_name='张三', depa_id=Depa{id=2, depa_name='美工部', emps=[]}, posts=[Post{id=1, post_name='职员', emps=[]}, Post{id=4, post_name='部门经理', emps=[]}]}
Emp{id=2, emp_name='李四', depa_id=Depa{id=1, depa_name='销售部', emps=[]}, posts=[Post{id=2, post_name='主管', emps=[]}]}
==> Preparing: SELECT * FROM emp e INNER JOIN depa d ON d.`id`=e.`depa_id` INNER JOIN emp_post ep ON ep.`emp_id`=e.`id` INNER JOIN post p ON p.`id`=ep.`post_id` WHERE e.`id` = ? AND e.`emp_name` IN ( ? , ? , ? )
==> Parameters: 2(Integer), 张三(String), 李四(String), 王五(String)
<== Columns: id, emp_name, depa_id, id, depa_name, emp_id, post_id, id, post_name
<== Row: 2, 李四, 1, 1, 销售部, 2, 2, 2, 主管
<== Total: 1
byIdAndNames------{mapIdName=2, mapNameList=[张三, 李四, 王五]}
Emp{id=2, emp_name='李四', depa_id=Depa{id=1, depa_name='销售部', emps=[]}, posts=[Post{id=2, post_name='主管', emps=[]}]}
==> Preparing: UPDATE emp SET emp_name = ?, depa_id = ? where id = ?
==> Parameters: Simon(String), 1(Integer), 1(Integer)
<== Updates: 1
saveOrUpdate-----true
==> Preparing: DELETE FROM emp WHERE id = ? OR id = ?
==> Parameters: 2(Integer), 3(Integer)
<== Updates: 2
del-----true
del-----2
==> Preparing: SELECT * FROM emp e INNER JOIN depa d ON d.`id`=e.`depa_id` INNER JOIN emp_post ep ON ep.`emp_id`=e.`id` INNER JOIN post p ON p.`id`=ep.`post_id`
==> Parameters:
<== Columns: id, emp_name, depa_id, id, depa_name, emp_id, post_id, id, post_name
<== Row: 1, Simon, 1, 1, 销售部, 1, 1, 1, 职员
<== Row: 4, 赵六, 1, 1, 销售部, 4, 4, 4, 部门经理
<== Row: 1, Simon, 1, 1, 销售部, 1, 4, 4, 部门经理
<== Total: 3
Emp{id=1, emp_name='Simon', depa_id=Depa{id=1, depa_name='销售部', emps=[]}, posts=[Post{id=1, post_name='职员', emps=[]}, Post{id=4, post_name='部门经理', emps=[]}]}
Emp{id=4, emp_name='赵六', depa_id=Depa{id=1, depa_name='销售部', emps=[]}, posts=[Post{id=4, post_name='部门经理', emps=[]}]}
==> Preparing: SELECT * FROM post p INNER JOIN emp_post ep ON ep.`post_id`=p.`id` INNER JOIN emp e ON e.`id`=ep.`emp_id` INNER JOIN depa d ON d.`id`=e.`depa_id`
==> Parameters:
<== Columns: id, post_name, emp_id, post_id, id, emp_name, depa_id, id, depa_name
<== Row: 1, 职员, 1, 1, 1, Simon, 1, 1, 销售部
<== Row: 4, 部门经理, 4, 4, 4, 赵六, 1, 1, 销售部
<== Row: 4, 部门经理, 1, 4, 1, Simon, 1, 1, 销售部
<== Total: 3
Post{id=1, post_name='职员', emps=[Emp{id=1, emp_name='Simon', depa_id=Depa{id=1, depa_name='销售部', emps=[]}, posts=[]}]}
Post{id=4, post_name='部门经理', emps=[Emp{id=4, emp_name='赵六', depa_id=Depa{id=1, depa_name='销售部', emps=[]}, posts=[]}, Emp{id=1, emp_name='Simon', depa_id=Depa{id=1, depa_name='销售部', emps=[]}, posts=[]}]}