目录
搭建MyBatis工作环境
- 动手开发MyBatis入门程序
- 数据交互层(DAO)的传统写法
- 使用MyBatis动态代理简化数据交互层(DAO)的写法
入门程序搭建与测试
开发步骤:创建工程、引入依赖Jar包、搭建日志输出环境、配置数据库连接池、创建持久层Java对象、编写Mapper配置文件和创建测试类。
数据库准备
相应的创建表SQL语句如下:
-- 创建数据库
CREATE DATABASE mybatis;
-- 使用创建的mybatis数据库
USE mybatis;
-- 创建表user
DROP TABLE IF EXISTS user;
CREATE TABLE user (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20) DEFAULT NULL,
password VARCHAR(20) DEFAULT NULL,
gender VARCHAR(5) DEFAULT NULL,
email VARCHAR(50) DEFAULT NULL,
province VARCHAR(20) DEFAULT NULL,
city VARCHAR(20) DEFAULT NULL,
birthday DATE DEFAULT NULL
);
-- 插入测试数据
INSERT INTO
user(id,username,password,gender,email,province,city,birthday)
VALUES
(1,'张三','1111','男','[email protected]','河南省','郑州市','1991-04-23'),
(2,'李四','2222','男','[email protected]','河北省','邯郸市','1989-10-13'),
(3,'刘丽','3333','女','[email protected]','江苏省','苏州市','1994-06-09'),
(4,'李丽','4444','女','[email protected]','四川省','成都市','1992-11-07');
搭建工程环境
使用MyBatis核心jar包为mybatis-3.4.1-jar,之外,还要准备MyBatis其他的依赖Jar包,并且准备数据库连接提供驱动,建立日志输出环境,最终,基本的mybatis程序结构和jar包如图:
数据库连接池配置文件
在mybatis-config.xml配置文件中,环境配置信息是配置在environments标签中,该标签中允许有多个environment标签,每一个单独的environment标签对应一个单独的数据库配置环境。transactionManager标签配置的事务管理类型,dataSource标签配置的是数据库的连接信息,其中包含多个property标签,用来配置数据库的驱动driver、数据库连接地址url、数据库用户名username和数据库密码password。
简单的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>
<!--数据源配置-->
<environments default="mysql">
<!--数据库配置的具体信息-->
<environment id="mysql">
<!--配置事务管理类型-->
<transactionManager type="JDBC"/>
<!--配置连接池信息-->
<dataSource type="POOLED">
<!--配置数据库的驱动、连接地址、用户名和密码-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="MARTIN0319"/>
</dataSource>
</environment>
</environments>
</configuration>
编写SQL映射配置文件
在MyBatis中,SQL语句与Java类并没有直接的联系,几乎所有的SQL语句配置都是在mapper的映射文件中,在MyBatis运行过程中,会读取配置中的SQL语句、输入和输出的参数类型。接下来在UserMapper.xml中添加一个select语句:
<?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="userTest">
<select id="findUserById" parameterType="integer" resultType="com.martin.domain.User">
select
id,username,password, gender,email,province,city,birthday
from
user
where
id = #{id}
</select>
</mapper>
在select标签中有如下几个属性:
- id:sql语句都被解析封装到mappedStatement对象中,对了调取对应的sql,需要一个唯一的标识符,id就是制定sql语句的唯一标识符;
- parameterType:指定输入的参数类型,例子中指定输入参数的类型为integer类型;
- resultType:指定输出的参数类型,例子中指定的输出映射成为User的Java对象;
- #{}:表示一个占位符,如果输入参数为Java的基本数据类型,那么#{}中的值可以为任意值;
编写完SQL映射文件后,为了让mybatis资源文件加载类能解析UserMapper.xml文件,需要把UserMapper.xml文件的路径配置在mybatis-config.xml中。
<mappers>
<mapper resource="com/martin/mapper/UserMapper.xml"/>
</mappers>
编写实体类和测试类
需要编写三个类,分别是持久化的实体类、数据库交互类(获取SqlSession)对象和测试类。
持久化实体类 — User
实体类中的成员变量与数据库表中的字段最好能够一一对应。类中的属性需要使用setter和getter方法来获取和设置。
User的实体类:
package com.martin.domain;
import java.util.Date;
public class User {
private Integer id;
private String username;
private String password;
private String gender;
private String email;
private String province;
private String city;
private Date birthday;
/*
setter、getter和toString方法略
*/
}
数据库交互类(获取SqlSession对象)
数据库交互类,资源文件加载类会读取数据库连接池的配置文件,然后SqlSessionFactory获取数据库连接数据和Mapper映射规则,从而创建出能够与数据库交互的SqlSession对象。
数据库交互工具类 - DataConnection.java
package com.martin.datasource;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class DataConnection {
private static String RESOURCE = "mybatis-config.xml";
private static SqlSessionFactory SESSIONFACTORY;
private static SqlSession SESSION;
public static SqlSession getSqlSession() throws IOException {
InputStream input = Resources.getResourceAsStream(RESOURCE);
SESSIONFACTORY = new SqlSessionFactoryBuilder().build(input);
SESSION = SESSIONFACTORY.openSession();
return SESSION;
}
}
在DataConnection类中,Resource资源加载类加载mybatis-config.xml配置文件,获取会话工厂SqlSessionFactory对象,之后调用SqlSessionFactory的openSession方法获取SqlSession对象。
编写测试类 — UserTest
编写测试类,该类需要从数据库中取出id为1的用户信息:
package com.martin.test;
import java.io.IOException;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.martin.datasource.DataConnection;
import com.martin.domain.User;
public class UserTest {
// 测试查找指定id的用户信息
@Test
public void testFindUserById() throws IOException {
SqlSession session = DataConnection.getSqlSession();
User user = session.selectOne("userTest.findUserById", 1);
System.out.println(user);
// 提交事务和关闭session
session.commit();
session.close();
}
}
在testFindUserById方法中:
- 通过DataConnection类获取SqlSession类的对象;
- 调用SqlSession类的selectOne方法,该方法中传入两个参数
- 第一个参数是SQL映射文件UserMapper.xml中namespace加上sql语句对应的id;
- 第二个参数是映射文件sql语句对应参数的参数值;
此时,在控制台,显示出了所执行的SQL语句和参数类型,并将查询到id为1的用户信息打印出来。
入门程序数据操作
以上实现了获取单个数据,如何进行多数据的查询和实现对数据增删改操作。
模糊查询 - selectList
对数据库中user表进行模糊查询,通过匹配名字中的某个字来查询用户:
首先在UserMapper.xml配置文件中配置SQL语句映射:
<select id="findUserByUsername" parameterType="string" resultType="com.martin.domain.User">
select
id,username,password, gender,email,province,city,birthday
from
user
where
username like '%${value}%'
</select>
其中的id仍然表示映射文件中的SQL被解析并转换成为Statement的id,parameterType指定SQL的输入参数的类型为String,而resultType指定结果类型为名为User的JavaBean。
select标签中对SQL语句的“${}”符号表示SQL的拼接。接收到的参数内容不加任何修饰的拼接在SQL语句中,在“${}”中只能使用value代表其中的参数。“${}”可以使用【"%"#{value}"%"】代替,此时括号中的value可以为任意字符。
在UserTest类中编写testFindUserByUsername方法来获取名字中含有“李”的用户信息:
@Test
public void testFindUserByUsername() throws IOException {
SqlSession session = DataConnection.getSqlSession();
List<User> userList = session.selectList("userTest.findUserByUsername", "李");
for (User user : userList) {
System.out.println(user);
}
// 提交事务和关闭session
session.commit();
session.close();
}
因为是模糊查询,所以查询得到的结果可能多于一个,SqlSession中可以通过selectList方法来获取多个对象,方法查询的结果为List类型。
此时,在控制台,显示出了所执行的SQL语句和参数类型为String类型,参数值为李,显示出查询到结果的数量为2,并将查询到用户名中包含“李”的用户信息打印出来。
增加用户 - insert
增加操作,使用的新增语句,需要在insert标签中添加sql语句,不需要返回值,由于需要插入的是一个User对象类型,所以此时parameterType的值为User类的全限定名称。
<insert id="insertUser" parameterType="com.martin.domain.User">
insert into
user(username,password,gender,birthday,email,province,city)
values
(#{username},#{password},#{gender},#{birthday,jdbcType=DATE},#{email},#{province},#{city})
</insert>
在插入Date属性birthday数值时,添加了一个jdbcType参数来声明该参数的Java类型符合JDBC的那种类型,方便在加载SQL语句设置参数时,能够正确的将格式映射到数据库中。
添加testInsertUser方法,向User表中插入一条数据:
@Test
public void testInsertUser() throws IOException, ParseException {
SqlSession session = DataConnection.getSqlSession();
User user = new User();
user.setUsername("孟祥杰");
user.setPassword("5555");
user.setGender("男");
user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1991-03-19"));
user.setProvince("江苏省");
user.setCity("沭阳县");
session.insert("userTest.insertUser",user);
// 提交事务
session.commit();
session.close();
}
获取插入实体的主键
对于有些业务,需要返回新增操作后对应实体的主键信息,在MySQL中的自增主键,在执行insert语句之前,MySQL会自动生成一个自增主键,在执行insert操作之后,通过MySQL的SELECT LAST_INSERT_()来获取刚插入记录的主键。
所以映射文件可以配置以下信息:
<insert id="insertUser" parameterType="com.martin.domain.User">
<selectKey keyProperty="id" order="AFTER" resultType="integer">
SELECT LAST_INSERT_ID()
</selectKey>
insert into
user(username,password,gender,birthday,email,province,city)
values
(#{username},#{password},#{gender},#{birthday,jdbcType=DATE},#{email},#{province},#{city})
</insert>
在insert标签插入selectKey标签,在标签中放置SELECT INSERT_LAST_ID()来查询最后一个自增主键。order参数表示该SQL函数相对于insert语句的执行时间,是在其之前(before)还是之后(after)。
还有一种获取自增主键的方式,就是在insert标签中添加属性“userGeneratedKeys”和“keyProperty”分别代表使用自增主键和Java对象的属性名称。配置如下:
<insert id="insertUser" parameterType="com.martin.domain.User" useGeneratedKeys="true" keyProperty="id">
insert into
user(username,password,gender,birthday,email,province,city)
values
(#{username},#{password},#{gender},#{birthday,jdbcType=DATE},#{email},#{province},#{city})
</insert>
进行完上面的设置,MyBatis执行insert语句之后,会将自增长id值赋值插入的对象User的属性id,然后在逻辑层就可以通过User的get方法获得到该id。
此时,控制台将所执行的插入语句和所插入的参数类型和各参数对应的值显示出来,并将自增的id打印出来。
修改和删除实体
对于删除和修改,同样要在UserMapper.xml配置文件中使用delete和update标签来编写相关的SQL配置:
<!-- 修改用户 -->
<update id="updateUser" parameterType="com.martin.domain.User">
update
user
set
username=#{username},
password=#{password},
gender=#{gender},
birthday=#{birthday,jdbcType=DATE},
email=#{email},
province=#{province},
city=#{city}
where
id=#{id}
</update>
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="com.martin.domain.User">
delete from
user
where
id=#{id}
</delete>
删除和修改的配置分别包裹在delete和update标签对中,传入的参数类型由parameterType来指定。这里配置修改和删除指定id的用户信息。在测试类 UserTest中分别新增testUpdateUser和testDeleteUser方法 :
// 修改用户信息
@Test
public void testUpdateUser() throws IOException, ParseException {
SqlSession session = DataConnection.getSqlSession();
// 获取ID为7的用户
User user = session.selectOne("userTest.findUserById",5);
// 修改用户的信息
user.setEmail("[email protected]");
// 调用update方法保存修改后的用户信息
session.update("userTest.updateUser", user);
// 提交事务和关闭session
session.commit();
session.close();
}
执行testUpdateUser方法后,控制台输出结果如图:
可以看到testUpdateUser方法后,被改变条数为1,也就是说成功的讲id为5的用户的email修改为[email protected]。
// 删除用户信息
@Test
public void testDeleteUser() throws IOException {
SqlSession session = DataConnection.getSqlSession();
// 获取ID为5的用户
User user = session.selectOne("userTest.findUserById",5);
// 调用delete删除用户
session.delete("userTest.deleteUser", user);
// 提交事务和关闭session
session.commit();
session.close();
}
执行testDeleteUser方法后,控制台输出结果如图:
可以看到,执行了delete方法后,被改变的条数为1,也就是说成功删除了id为5的用户的数据。