抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

本章学习使用MyBatis框架进行CRUD操作(基于代理dao模式),使用Dao实现类的方式CRUD操作、MyBatis中参数深入及结果集的深入、MyBatis中主配置的标签使用、实体类的别名等。

MyBatis框架中的CRUD操作

一、前期准备

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
32
33
34
<?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>002</groupId>
<artifactId>002</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
</project>

2、创建SqlMapConfig.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">
<!-- mybatis的主配置文件 -->
<configuration>
<!-- 配置环境 -->
<environments default="development">
<!-- 配置mysql环境 -->
<environment id="development">
<!-- 配置事务类型 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(也叫连接池) -->
<dataSource type="POOLED">
<!-- 配置连接数据库的4个基本信息 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/eesy_mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>

<!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
如果是用注解来配置的话,此处应该使用class属性指定被注解的dao全限定类名
-->
<mappers>
<mapper resource="com/itheima/dao/IUserDao.xml"/>
<!--<mapper class="com.itheima.dao.IUserDao"/>-->
</mappers>
</configuration>

3、常见实体类

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

import java.util.Date;

public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;

public User() {
}

public User(Integer id, String username, Date birthday, String sex, String address) {
this.id = id;
this.username = username;
this.birthday = birthday;
this.sex = sex;
this.address = address;
}

public Integer getId() {
return id;
}

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

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 getSex() {
return sex;
}

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

public String getAddress() {
return address;
}

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

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

4、常见接口在内部定义CRUD的方法

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

import com.itheima.domain.User;

import java.util.List;

public interface IUserDao {
/**
* 查询所有
* @return
*/
List<User> findByAll();

/**
* 查询一个
* @param id 要查询的用户id
* @return
*/
User findByOne(int id);

/**
* 根据用户姓名进行模糊查询
* @param name 模糊查询的条件
* @return
*/
List<User> findByLike(String name);

/**
* 保存用户
* @param user
* @return
*/
int addUser(User user);

/**
* 修改用户信息
* @param user
*/
int updateUser(User user);

/**
* 删除用户信息
* @param id
*/
void deleteUser(int id);
}


二、编写映射文件并测试运行

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
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
<?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="com.itheima.dao.IUserDao">
<!-- 查询所有并封装到一个List集合 -->
<select id="findByAll" resultType="com.itheima.domain.User">
select * from user
</select>

<!-- 查询一个用户对象 -->
<select id="findByOne" resultType="com.itheima.domain.User" parameterType="int">
select * from user where id = #{id}
</select>

<!-- 模糊查询用户 -->
<select id="findByLike" parameterType="string" resultType="com.itheima.domain.User">
<!-- 使用这种方式不需要在传入参数时还加“%” -->
select * from user where username like '%${value}%'
</select>

<!-- 保存一个用户 -->
<insert id="addUser" parameterType="com.itheima.domain.User">
<!-- 返回插入的数据的id属性 -->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id()
</selectKey>
insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>

<!-- 修改用户信息 -->
<!-- parameterType属性:代表参数的类型,由于传入的是一个类对象,所以类型就写类的全名称 -->
<update id="updateUser" parameterType="com.itheima.domain.User">
update user
<set>
<if test="username != null">
username = #{username},
</if>
<if test="sex != null">
sex = #{sex},
</if>
<if test="birthday != birthday">
birthday = #{birthday},
</if>
<if test="address != null">
address = #{address}
</if>
</set>
where id = #{id}
</update>

<!-- 删除一个用户信息 -->
<!-- 由于此时传入的参数类型是int类型的,所以写的是int(也可以是java.lang.Integer或INT) -->
<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>
</mapper>

该映射文件中的**#{}字符可以理解为和原来sql部分学习的“?**”一样,都是占位符。

parameterType的参数是一个简单类型(基本类型8种+String)的时候,#{}中的值可以任意写,如果是一个对象(例如User),则必须使用属性名称。


ognl 表达式:

​ 它是 apache 提供的一种表达式语言,全称是:

​ Object Graphic Navigation Language 对象图导航语言

​ 它是按照一定的语法格式来获取数据的。

​ 语法格式就是使用 #{对象.对象}的方式


#{}和${}的区别:

  • #{}表示一个占位符

    通过#{}可以实现perparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。#{}可以接收简单类型值或pojo属性值

  • ${}表示拼接sql串

    通过${}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换, ${}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。


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

import com.itheima.dao.IUserDao;
import com.itheima.domain.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class IUserDaoTest {
private InputStream in = null;
private SqlSession session = null;
private IUserDao userDao;

@Before
public void init() throws Exception {
//读取配置文件,使用输入输出流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建SqlSessionFactory工厂(用于创建数据库连接对象)
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//使用工厂生产SqlSession对象
session = factory.openSession();
//使用SqlSession创建Dao接口的代理对象(增强其中的方法)
userDao = session.getMapper(IUserDao.class);
}

@After
public void destroy() throws Exception {
//手动提交
session.commit();
//释放资源
session.close();
in.close();
}

/**
* 查询所有
*/
@Test
public void findByUserTest(){
List<User> users = userDao.findByAll();
for (User user : users) {
System.out.println(user);
}
}

/**
* 查询一个用户对象
*/
@Test
public void findByOneTest(){
User user = userDao.findByOne(43);
System.out.println(user);
}

@Test
public void findByLikeTest(){
List<User> users = userDao.findByLike("王");
for (User user : users) {
System.out.println(user);
}
}

/**
* 向数据库中添加一条数据
*/
@Test
public void addUserTest(){
User user = new User(null,"wangwu",new Date(),"男","西安");
System.out.println(userDao.addUser(user));
System.out.println(user);
}

/**
* 修改数据库中一条信息
*/
@Test
public void updateUserTest(){
User user = new User(53,"wangwu",null,"男",null);
System.out.println(userDao.updateUser(user));
}

/**
* 删除用户信息
*/
@Test
public void deleteUserTest(){
userDao.deleteUser(49);
}
}


三、MyBatis参数深入

在上一章节中已经介绍了 SQL 语句传参,使用标签的 parameterType 属性来设定。该属性的取值可以是基本类型,引用类型(例如:String 类型),还可以是实体类类型(POJO 类)。同时也可以使用实体类的包装类,本章节将介绍如何使用实体类的包装类作为参数传递。


1、MyBatis中的基本数据类型别名

基本数据类型即可以直接写类型名称,也可以使用包名,类名的方式。

例如String既可以写成类型名称(String)也可以写成全限定类名(java.lang.String)。

官方文档给出了基本数据类型的别名说明文档

基本数据类型的别名

2、传递POJO包装对象

开发过程中可以通过POJO传递查询条件,查询条件是综合的查询条件,不仅包括用户查询条件还包括其他的查询条件(例如将用户的购买商品也作为查询条件),这时可以使用包装对象传递参数。

(1)实例——编写QueryVo类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class QueryVo {
private User user;

public QueryVo() {
}

public QueryVo(User user) {
this.user = user;
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}
}

(2)实例——编写持久层接口

1
2
3
4
5
6
7
8
9
10
11
12
13
import com.itheima.domain.QueryVo;
import com.itheima.domain.User;

import java.util.List;

public interface IUserDao {
/**
* 根据QueryVo中的条件查询用户
* @param queryVo POJO类
* @return
*/
List<User> findByVo(QueryVo queryVo);
}

(3)实例——测试包装类查询

1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void findByVoTest(){
QueryVo queryVo = new QueryVo();
User user1 = new User();
user1.setUsername("%王%");
queryVo.setUser(user1);
List<User> users = userDao.findByVo(queryVo);
for (User user: users) {
System.out.println(user);
}

}


四、MyBatis的输出结果的封装

1、resultType配置结果类型

resultType属性可以指定封装结果集的类型,它支持基本类型和实体类型。

resultType和parameterType一样,如果注册过类型别名的可以直接使用别名。没有注册过的必须使用全限定类名。

同时还有一个要求实体类中的属性名称必须和查询语句中的列明保持一致,否则无法实现封装。


2、resultMap结果类型

resultMap标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。

在select标签中使用resultMap属性指定引用即可。同时resultMap可以实现将查询结果映射为复杂类型的POJO,例如在查询结果映射对象中包括POJO和List实现一对一和一对多查询。


(1)定义resultMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 建立User实体和数据库表的对应关系
属性说明
type属性:指定实体类的全限定类名
id属性:给定一个唯一标识,是给查询select标签引用的
-->
<resultMap id="userMap" type="com.itheima.domain.User">
<id column="id" property="userid"/>
<result column="username" property="userName"/>
<result column="birthday" property="userBirthday"/>
<result column="sex" property="userSex"/>
<result column="address" property="userAddress"/>
</resultMap>
<!--
标签说明
id标签:用于指定主键字段
result标签:用于指定非主键字段
column属性:用于指定数据库列名
property属性:用于指定实体类属性名称
-->

(2)映射配置

1
2
3
4
<!-- 查询所有并封装到一个List集合 -->
<select id="findByAll" resultMap="userMap">
select * from user
</select>

(3)测试及相应结果

1
2
3
4
5
6
7
8
9
10
/**
* 查询所有
*/
@Test
public void findByUserTest(){
List<User> users = userDao.findByAll();
for (User user : users) {
System.out.println(user);
}
}
运行结果

五、SqlMapConfig.xml配置文件

1、配置的内容与顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-properties(属性)
--property
-setting(全局配置参数)
--setting
-typeAliases(类型别名)
--typeAliase
--packge
-typeHandlers(类型处理器)
-objectFactory(对象工厂)
-plugins(插件)
-environments(环境集合属性对象)
--environment(环境集合子属性对象)
--transactionManager(事务管理)
--dataSource(数据源)
-mappers(映射器)
--marpper
--package

2、properties标签配置

配置连接数据库的信息

resource 属性:用于指定 properties 配置文件的位置,要求配置文件必须在类路径下resource=”jdbcConfig.properties”

url 属性:

URL: Uniform Resource Locator 统一资源定位符

http://localhost:8080/mystroe/CategoryServlet URL

​ 协议 主机 端口 URI

URI:Uniform Resource Identifier 统一资源标识符

​ /mystroe/CategoryServlet

​ 它是可以在 web 应用中唯一定位一个资源的路径



六、类型别名

1、自定义别名

在SqlMapConfig.xml中配置:

1
2
3
4
5
6
7
<typeAliases>
<!-- 单个别名定义 -->
<typeAlias alias="user" type="com.itheima.domain.User"/>
<!-- 批量别名定义,扫描整个包下的类,别名为类名(字母大小写均可) -->
<package name="com.itheima.domain"/>
<package name="其他包"/>
</typeAliases>

alias属性:被定义的别名名称。

type属性:被定义别名的类的全限定类名。



七、mappers(映射器)

1、使用相对类路径的资源


2、使用mapper接口类路径

注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。


3、注册指定包下的所有 mapper 接口

注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。






参考资料:

传智黑马MyBatis阶段视频:

评论