文章结构
Mybatis简介
mybatis是一种持久层框架,简化jdbc代码,实现对数据库的操作。
因为内存中的数据,随着程序的终止或者变量的改变就会消失,所以需要持久化技术将数据保存下来,所谓持久层技术,简单的来说就是将内存中的数据保存到存储设备(如硬盘)。可以保存到txt文件,也可以保存到数据库中
持久层就是实现持久化工作的代码块
开发环境及依赖版本号
jdk 8
mysql 5.6.47
maven 3
mybatis 3.5.2
mysql-connector-java 5.1.47
junit 4.12
IDEA 2017
基于配置文件实现Mybatis
流程:(添加测试数据)–>搭建maven环境–>导入相关依赖–>编写Mybatis配置文件–>编写Mybatis工具类–>创建实体类–>编写Mapper接口类–>编写Mapper.xml配置文件–>测试。
在数据库没有测试数据的情况下我们先添加一些测试数据。
1、添加测试数据
1.1 创建测试数据库
create database mybatis;
use mybatis;
drop table if exists user;//如果测试数据库中有user表即删除
create table user(
id int(20) not null,
name varchar(20) default null,
pwd varchar(20) default null,
primary_key(id)
)engine=innodb default charset=ut8;
1.2 插入测试数据
insert into user(id,name,pwd) values(1,'张三','123456'),(2,'李四',123456),(3,'赵五',123456)
2、创建maven工程
1.1添加持久层mybatis,数据库驱动mysql-connector,测试工具junit依赖
<?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.kss</groupId>
<artifactId>mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
3、编写Mybatis配置文件
可以看出一些原来的jdbc参数,在mybatis中是写在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="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/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper.xml"/>
</mappers>
</configuration>
4、编写Mybatis工具类
Mybatis工具类主要涉及到读取mybatis-config.xml配置文件,并获取一个静态SqlSessionFactory实例,并通过getSession()方法获取一个SqlSession实例。SqlSession实例类似于jdbc中的connection。
package com.kss.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.File;
import java.io.IOException;
import java.io.InputStream;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
//读取配置文件
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession连接
public static SqlSession getSession() {
return sqlSessionFactory.openSession();
}
}
5、创建实体类
值得注意的是对于一个javabean必须要有一个无参构造函数。
package com.kss.pojo;
public class User {
private int id;
private String name;
private String pwd;
//构造函数:有参和无参
//set和get方法
//重写toString()
}
6、编写Mapper方法
这里的UserMapper只是一个接口,为了实现接口,我们还需要继续编写一个Mapper配置文件。如果好奇Mapper是一个接口但为什么能实现功能,可以参考这篇文章
package com.kss.mapper;
import com.kss.pojo.User;
import java.util.List;
public interface UserMapper {
List<User> selectUser();
}
7、编写Mapper配置文件
namespace的参数值是mapper类路径
resultType的参数值是实体类User的类路径,表示将返回数据与User关联起来
select id的参数值是UserMapper对应的方法签名,表示调用selectUser()实现了select * from user的操作。
<?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.kss.mapper.UserMapper">
<select id="selectUser" resultType="com.kss.pojo.User">
select * from user
</select>
</mapper>
8、测试
可以看出之所以要编写一个Mybatis工具类是为了封装读取配置文件,获取SqlSessionFactory实例的代码,通过MybatisUtils.getSession()就可以轻松获取一个Session实例,之后的操作就在session的基础上进行。操作结束之后记得调用session.close()关闭资源。所以说Mybatis是对jdbc的简化,在使用mybatis的过程中仍能看到jdbc的影子。
8.1测试代码
package com.test;
import com.kss.mapper.UserMapper;
import com.kss.pojo.User;
import com.kss.util.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class MyTest {
@Test
public void selectUser(){
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.selectUser();
for (User user : users) {
System.out.println(user.toString());
}
session.close();
}
}
8.2 测试结果
9、项目组织结构
增删改查
0、预备工作
在执行增删改查之前先修改下全局配置文件mybatis_config.xml
在configure中添加typeAiases来定义别名。之前的Mapper配置文件中,select语句的resultType的参数值是实体类的全路径,使用了实体类之后就可以直接使用实体类的小写类名作为resultType
<configuration>
<!--typeAiases可以用来自定义别名-->
<!--常用的做法是利用包扫描来批量定义,批量定义默认的类的别名是类名首字母小写-->
<!--如下的配置,我们在mapper.xml中可以用user代替User的全路径-->
<typeAliases>
<package name="com.kss.pojo"></package>
</typeAliases>
<!--使用别名前-->
<select id="selectUser" resultType="com.kss.pojo.User">
select * from user
</select>
<!--使用别名后-->
<select id="selectUser" resultType="user">
select * from user
</select>
1、通过id查找唯一的用户信息
在mapper配置文件中增加SQL插入语句
<!--通过id查找记录-->
<select id="selectUserById" resultType="user">
select * from user where id=#{id};
</select>
在UserMapper接口中添加findUseById(int id)方法
User selectUserById(int id);
测试
public class MyTest {
SqlSession session;
UserMapper mapper;
@Before
public void init(){
session = MybatisUtils.getSession();
mapper = session.getMapper(UserMapper.class);
}
@Test
public void test(){
int id=2;//确保数据库中有id为2的用户
User u = mapper.selectUserById(id);
System.out.println(u.toString());
}
@After
public void close() {
session.close();
}
}
测试结果
2、删除用户信息
在mapper配置文件中增加SQL删除语句,parameterType指定参数类型。SQL语句中的#{id}类似preparedStatement中的占位符。
<!--删除-->
<delete id="deleteUserById" parameterType="java.lang.Integer">
DELETE FROM user WHERE id=#{id};
</delete>
在userMapper接口中添加deleteUserById()方法
int deleteUserById(int id);
测试代码
执行deleteUserById(id)后返回的是受到影响的行数,由于一般一个id只能对应一条记录,所以返回1。
//有bug
public class MyTest {
SqlSession session;
UserMapper mapper;
@Before
public void init() {
session = MybatisUtils.getSession();
mapper = session.getMapper(UserMapper.class);
}
@Test
public void test() {
// int id=2;
// User u = mapper.selectUserById(id);
// System.out.println(u.toString());
int del = mapper.deleteUserById(2);
System.out.println(del);
List<User> users = mapper.selectUser();
for (User user : users) {
System.out.println(user.toString());
}
}
@After
public void close() {
session.close();
}
}
测试结果
测试结果中虽然没有了id=2的记录,当时在数据库中这条记录还是存在的。之所以会这样子是因为没有在删除之后提交
//修改版本
public class MyTest {
SqlSession session;
UserMapper mapper;
@Before
public void init() {
session = MybatisUtils.getSession();
mapper = session.getMapper(UserMapper.class);
}
@Test
public void test() {
// int id=2;
// User u = mapper.selectUserById(id);
// System.out.println(u.toString());
int del = mapper.deleteUserById(2);
System.out.println(del);
session.commit();
List<User> users = mapper.selectUser();
for (User user : users) {
System.out.println(user.toString());
}
}
@After
public void close() {
session.close();
}
}
3、更新用户信息
在mapper配置文件增加update语句
这里传入的参数是user,即一个实体,mybatis会自动使用get方法获取user实体中的name和id,所以要确保User类中有对应的get方法。
<!--修改-->
<delete id="updateUser" parameterType="user">
UPDATE user SET name=#{name} where id=#{id};
</delete>
在mapper接口中增加updateUser方法
int updateUser(User user);
测试代码
@Test
public void test() {
User u = mapper.selectUserById(3);
u.setName("李六");
int update = mapper.updateUser(u);
session.commit();
List<User> users = mapper.selectUser();
System.out.println(update);
for (User user : users) {
System.out.println(user.toString());
}
}
测试结果、
调用updateUser的返回值依然是受SQL影响的行数,这这里同样要记得执行session.commit()
4、添加用户信息
在mapper配置文件增加insert语句
这里传入的参数是user
<!--插入-->
<insert id="addUser" parameterType="user">
insert into user(id,name,pwd) values(#{id},#{name},#{pwd});
</insert>
在mapper接口中增加addUser方法
int addUser(User user);
测试代码
@Test
public void test() {
User u=new User();
u.setId(6);
u.setName("王二");
u.setPwd=("abcd");
int add=mapper.addUser(user);
session.commit();
System.out.println(add);
List<User> users = mapper.selectUser();
for (User user : users) {
System.out.println(user.toString());
}
}
测试结果、
调用addUser的返回值依然是受SQL影响的行数,因为只插入一条信息所以返回1,当返回0时则说明插入失败。这里同样要记得执行session.commit()