mybatis阶段,需要创建maven项目,导入的依赖都是基本的dep,导入的配置文件有三个,分别是:jdbc.properties、log4j.properties、mybatis-config.xml。第一个负责数据库的基本参数定义,第二个负责日志打印,第三个负责引入数据库连接(需要引用第一个文件)以及指出我们书写的mapper的位置,这个核心配置文件可以扩展很多种功能,比如驼峰命名驼峰命名,主要以xml的方式写sql

创建maven项目

选择project

UhNuod.png

选择maven项目

UhNQJI.png

项目创建时选项

UhNZLD.png

之后就一路确认即可

项目配置文件

如果你项目创建正确,是这样的

UhNndH.png

首先去 pom文件里引入依赖,pom.xml在最下面

要确定你idea中的mevenjar包位置是你自己指定的哦

UhNMFA.png

这里的pom直接导入就行,要放在project 里

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
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>


<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>


<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
<!--这里的 scope意为约束,表示只能在src的 约束文件内使用,这里指的是 只能在src的test文件夹下使用junit-->
</dependency>

<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>


</dependencies>

等待也是一种成功

上面的jar包如果是第一次导入的话,有可能会下载一会,所以这里我们要等jar下载完毕

开始正式流程

mybatis的配置文件书写,位置是在resources中,首先写一个日志文件,用来打印你的查询结果的

log4j.properties:

1
2
3
4
5
6
7
8
log4j.rootLogger = debug,stdout


### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

书写mybatis核心配置

mybatis-config.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
<?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>
<!--引入jdbc属性配置-->
<properties resource="jdbc.properties"></properties>
<!--mybatis的核心环境配置-->
<environments default="development">
<environment id="development">
<!--
在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施
MANAGED – 这个配置几乎没做什么
-->
<transactionManager type="JDBC"/>
<!--type可选值:UNPOOLED 不使用连接池
POOLED使用连接池
JNDI 从配置好的JNDI数据源获取连接池-->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>

书写jdbc 连接数据库!

书写基本的配置文件,但是实际上这个文件只是用来被主配置文件调用的,并不会直接被用到

jdbc.properties

1
2
3
4
5
#注意mybatis版本>=6.0使用如下驱动
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/20_0720?useUnicode=true&characterEncoding=UTF-8&&serverTimezone=UTC&useSSL=false
username=root
password=root

在mysql导入数据

mysql数据导入
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
DROP TABLE IF EXISTS `brands`;

CREATE TABLE `brands` (
`brand_id` int NOT NULL AUTO_INCREMENT COMMENT '品牌ID',
`brand_name` varchar(100) DEFAULT NULL COMMENT '品牌名称',
`brand_img` varchar(150) DEFAULT NULL COMMENT '品牌图标',
PRIMARY KEY (`brand_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

/*Data for the table `brands` */

insert into `brands`(`brand_id`,`brand_name`,`brand_img`) values (1,'瑞士莲','/img/lindt_chocolate.img'),(2,'德芙','/img/dove.img'),(3,'费列罗','/img/FERRERO_ROCHER.img');

/*Table structure for table `orders` */

DROP TABLE IF EXISTS `orders`;

CREATE TABLE `orders` (
`order_id` int NOT NULL COMMENT '订单编号',
`user_id` int NOT NULL COMMENT '下单用户id',
`order_price` double NOT NULL COMMENT '订单金额',
`payment` varchar(20) DEFAULT NULL COMMENT '支付方式',
`state` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '订单状态',
`order_createtime` date DEFAULT NULL COMMENT '下单时间',
`note` varchar(100) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`order_id`),
KEY `FK_orders_1` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `orders` */

insert into `orders`(`order_id`,`user_id`,`order_price`,`payment`,`state`,`order_createtime`,`note`) values (10000563,6,100,'会员','已支付','0202-03-21','汽车精洗'),(10000564,8,600,'支付宝','已支付','2020-03-26','土豪客户'),(10000565,6,320,'会员','已支付','2020-03-29','普通保养'),(10000566,10,80,'微信','已退单','2020-03-29','预约洗车,取消订单');

/*Table structure for table `product` */

DROP TABLE IF EXISTS `product`;

CREATE TABLE `product` (
`product_id` varchar(32) NOT NULL COMMENT '商品ID',
`product_img` varchar(50) DEFAULT NULL COMMENT '商品图片',
`product_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '商品名称',
`product_sale` int DEFAULT NULL COMMENT '商品销量',
`stock` int DEFAULT NULL COMMENT '商品库存',
`product_price` double DEFAULT NULL COMMENT '商品价格',
`brandid` int DEFAULT NULL COMMENT '品牌ID',
PRIMARY KEY (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `product` */

insert into `product`(`product_id`,`product_img`,`product_name`,`product_sale`,`stock`,`product_price`,`brandid`) values ('p01','/img/dove/213231.img','Dove/德芙丝滑牛奶巧克力252g碗装排块糖果糖巧休闲零食品',1800062,2000000,29.9,2),('p02','/img/dove/352342.img','德芙麦提莎麦丽素麦芽脆夹心巧克力豆520g/桶装休闲零食糖果',209710,300000,79.9,2),('p03','/img/dove/635987.img','Dove/德芙丝滑牛奶巧克力252g*2碗装排块休闲零食品糖果',344410,500000,59.8,2),('p04','/img/rocher/845127.img','费列罗榛果巧克力48粒送女友零食婚庆礼盒3*16条喜糖糖果礼',563315,1000000,139,3),('p05','/img/rocher/345311.img','费列罗拉斐尔椰蓉扁桃仁糖果酥球10粒 休闲零食',19460,25000,79.9,3);

/*Table structure for table `tab_student` */

DROP TABLE IF EXISTS `tab_student`;

CREATE TABLE `tab_student` (
`sid` int NOT NULL AUTO_INCREMENT COMMENT '学生ID',
`student_name` varchar(30) DEFAULT NULL COMMENT '姓名',
`student_birthday` date DEFAULT NULL COMMENT '生日',
`student_height` double DEFAULT NULL COMMENT '身高',
`sex` varchar(2) DEFAULT NULL COMMENT '性别',
PRIMARY KEY (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

/*Data for the table `tab_student` */

insert into `tab_student`(`sid`,`student_name`,`student_birthday`,`student_height`,`sex`) values (1,'褚英才','1997-02-01',175,'男'),(2,'绍洋','1999-08-21',160,'女'),(3,'司徒玉','2000-10-12',162,'女'),(4,'孟杨','1999-06-08',172,'男'),(5,'郎桂芝','1998-10-26',168,'女');

/*Table structure for table `tab_student_teacher` */

DROP TABLE IF EXISTS `tab_student_teacher`;

CREATE TABLE `tab_student_teacher` (
`id` int NOT NULL AUTO_INCREMENT,
`sid` int DEFAULT NULL COMMENT '学生ID',
`tid` varchar(32) DEFAULT NULL COMMENT '老师ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

/*Data for the table `tab_student_teacher` */

insert into `tab_student_teacher`(`id`,`sid`,`tid`) values (1,1,'T001'),(2,2,'T001'),(3,1,'T002'),(4,3,'T002'),(5,5,'T002'),(6,2,'T003');

/*Table structure for table `tab_teacher` */

DROP TABLE IF EXISTS `tab_teacher`;

CREATE TABLE `tab_teacher` (
`tid` varchar(32) NOT NULL COMMENT '老师ID',
`tname` varchar(30) DEFAULT NULL COMMENT '姓名',
`tsex` varchar(3) DEFAULT NULL COMMENT '性别',
PRIMARY KEY (`tid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `tab_teacher` */

insert into `tab_teacher`(`tid`,`tname`,`tsex`) values ('T001','韩老师','男'),('T002','董老师','男'),('T003','茆老师','女');

/*Table structure for table `user` */

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
`uid` int NOT NULL AUTO_INCREMENT,
`username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名称',
`birthday` date DEFAULT NULL COMMENT '生日',
`phone` varchar(15) DEFAULT NULL COMMENT '手机号',
`sex` char(2) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;

/*Data for the table `user` */

insert into `user`(`uid`,`username`,`birthday`,`phone`,`sex`,`address`) values (1,'王五','1996-12-25',NULL,NULL,NULL),(2,'小花','1998-06-02','13659596872','2','江苏沭阳'),(6,'张小明','1996-01-06','15263671526','2','江苏南京'),(8,'张三丰','1998-12-25','15966633888','1','北京朝阳'),(10,'张三','1998-10-16','15777778696','1','北京海淀'),(12,'刘皇叔','2000-03-22','17888888888','1','江苏连云港');

创建一个实体类

实体类位置:

UhNmee.png

实体类代码:

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
package com.ls.mybatis.model;

import java.util.Date;

public class User {
private int uid;
private String username;
private Date birthday;
private String phone;
private String sex;
private String address;

public User() {
}

public User(int uid, String username, Date birthday, String phone, String sex, String address) {
this.uid = uid;
this.username = username;
this.birthday = birthday;
this.phone = phone;
this.sex = sex;
this.address = address;
}

@Override
public String toString() {
return "User{" +
"uid=" + uid +
", username='" + username + '\'' +
", birthday=" + birthday +
", phone='" + phone + '\'' +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}

public int getUid() {
return uid;
}

public void setUid(int uid) {
this.uid = uid;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public Date getBirthday() {
return birthday;
}

public void setBirthday(Date birthday) {
this.birthday = birthday;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}
}

编写mapper ,书写查询代码

UserMapper.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
<?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">
<mapper namespace="test">

<!--
id:sql片段的唯一标识,同一个mapper文件中不能重复
parameterType:参数类型
resultType:返回值类型
-->
<select id="selectOne" resultType="com.ls.mybatis.model.User">
SELECT
uid,
username,
birthday,
phone,
sex,
address
FROM `user`
WHERE uid = #{id}
</select>

</mapper>

mapper 的namespace 必须要指定,还有 映射语句的id 这个是这个查询语句的唯一标识,调用的时候: namespace的id . 映射语句id

此时项目目录结构

UhN3SP.png

最后书写测试类 测试代码

测试代码位置

UhNlWt.png

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    @Test
public void selectOne() throws IOException {
//文件位置
String resource = "mybatis-config.xml";
//读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建session工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
//可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
SqlSession sqlSession = sqlSessionFactory.openSession();

//通过 namespace.id的方式确定要执行的SQL片段
//
User o = sqlSession.selectOne("test.selectOne", 2);

System.out.println(o);
//用完后必须管理连接
sqlSession.close();

运行效果

UhNteg.png

详解各个配置文件

mybatis 核心配置文件

jdbc引入

1
2
 <!--引入jdbc属性配置-->
<properties resource="jdbc.properties"/>

开启驼峰式命名:

主要用于约束实体类,userName与user_name,userPhone与user_phone,开启后 数据库中的 _a == 实体类中的 A ( _a ==A)

1
2
3
4
<settings>
<!--开启驼峰规则映射-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

取别名:

给 .xml 中的resultType顾名思义: 结果类型,然而一般情况下,我们要将这个包名在项目中的位置详细写出来,但是通常,每一个sql都写一个比较长的返回值,还是多少让人头大的,所以为了达到简写的目的,可以将一个实体类进行命名,如果嫌挨个命名也麻烦,可以干脆指定实体类的父包,就会默认取小写的实体类名,比如 User 取user

1
2
3
4
5
6
7
<typeAliases>
<!--给某一个类取别名-->
<typeAlias type="com.czxy.mybatis.model.User" alias="user"></typeAlias>
<!--扫描某一个包下的类,指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean-->
<!--这样有10个或者100个类不用一个个取指定别名-->
<package name="com.czxy.mybatis.model"/>
</typeAliases>

mybatis的核心环境配置:

比如你的项目有测试环境和开发环境,有可能会切换操作环境,通过 datasource的三个配置参数,可以确定这个数据库到底去不去使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<environments default="development">
<environment id="development">
<!--
transactionManager:配置事务管理器
MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施
MANAGED – 这个配置几乎没做什么
-->
<transactionManager type="JDBC"/>
<!--
dataSource: 配置数据源
type可选值:UNPOOLED 不使用连接池
POOLED使用连接池
JNDI 从配置好的JNDI数据源获取连接池-->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>

总的来说,就是要通过核心配置类将 map书写的查询代码,jdbc的链接参数,都囊括进来

2、 jdbc 链接设置

常用基本的四个参数为

mysql驱动名

mysql链接地址

mysql用户名

mysql用户密码

UhN8Qf.png

在mabatis核心文件中用${命名} 调用

3、书写sql的mapper

parameterType,指的是传入sql的参数的类型

#{} 代表用 ?占位符的方式获取属性值,可以避免sql注入 将参数 更改为 被 双引号括起来的形式,此时如果有注入的参数为: where a = “1 or 4 = 4” 本来我们没有写的and 4 =4 就是坏人恶意查询,但是此时会被这种占位添加双引号,所以恶意查询失效

${} 代表是直接将 数据的条件直接转换为可执行的条件 where a = 1 or 4 = 4 这样便会将我们没有写入过的程序强行写入,造成数据泄露,无法挽回

参数数量为1的时候,参数占位符内可以随意命名

UhNGy8.png

参数数量为多个的时候

U4Eipn.png

parameterType此时需要自己设置, 可以写别名 map 否则需要自己制定全类名 java.util.Map,也可以不写,他会自己找类型的,因为多个参数只是用一个类型无法接收,map最合适

接受的参数也可以是实体类(pojo)

4、编写测试类

普通类型上面已经贴了,这里写点不一样的,可以通过输入map集合进行查询:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
        String resource = "mybatis-config.xml";
//读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建session工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
//可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
SqlSession sqlSession = sqlSessionFactory.openSession();

HashMap<String, Object> stringObjectHashMap = new HashMap<String, Object>();
stringObjectHashMap.put("phone", "15777778696");
stringObjectHashMap.put("sex", "1");


//通过 namespace.id的方式确定要执行的SQL片段
//
List<User> objects = sqlSession.selectList("test.listUser", stringObjectHashMap);

System.out.println(objects);
//用完后必须关闭连接
sqlSession.close();

可以通过书写sql时候指定的resultType为 map类型 意味返回map类型数据,接收参数的时候,以map接收:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void selectThree() throws IOException {
String resource = "mybatis-config.xml";
//读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建session工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
//可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
SqlSession sqlSession = sqlSessionFactory.openSession();

List<Map<String,Object>> objects = sqlSession.selectList("test.l2");

for (Map<String, Object> object : objects) {
Object username = object.get("username");
System.out.println(username.toString());
}
//用完后必须关闭连接
sqlSession.close();
}

模糊查询的 百分号 需要在后端添加:

1
2
3
4
5
6
HashMap<String, Object> map = new HashMap<>();
map.put("phone","%"+6+"%");
map.put("sex","1");

//通过 namespace.id的方式确定要执行的SQL片段
List<User> list = sqlSession.selectList("test.listUser2", map);

这些都是一对一查询

5、log4j参数

debug 日志级别,常用的4个日志级别:ERROR、WARN、 INFO、DEBUG

贴个全面代码,看看就懂了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#log4j.rootLogger = debug,stdout,D,E

### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
#log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
#log4j.appender.D.File = E://logs/log.log
#log4j.appender.D.Append = true
#log4j.appender.D.Threshold = DEBUG
#log4j.appender.D.layout = org.apache.log4j.PatternLayout
#log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

### 输出ERROR 级别以上的日志到=E://logs/error.log ###
#log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
#log4j.appender.E.File =E://logs/error.log
#log4j.appender.E.Append = true
#log4j.appender.E.Threshold = ERROR
#log4j.appender.E.layout = org.apache.log4j.PatternLayout
#log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

mybatis核心配置文件中的标签,有约束,要有一定的书写顺序,不能打乱,可以通过ctrl + 左键 点击configuration查看

${}可以用来 配合 group by 使用 将 所需的字段映射为所需字段group by uid 不需要占位符刻意变成字符串的操作了