一.MyBatis简介
是一个基于Java的持久框架层,它支持自定义 SQL、存储过程以及高级映射。
Mybatis免除了所有的JDBC代码和参数的设置及获取结果集的工作,使用简单的XML或注解来配置和映射接口、实体类为数据库中的记录。
优点:
(1)Mybatis消除了大量的JDBC冗余代码
(2)Mybatis提供了与Spring框架的集成支持
(3)Mybatis可以接受SQL语句
(4) Mybatis能很好地与传统数据库协同工作
(5) Mybatis提供了与第三方缓存类库的集成支持
二.Mybatis工作流程
读取配置文件
加载映射文件
构造会话工厂SqlSessionFactory
通过工厂创建会话对象sqlSession
通过会话对象执行SQL语句
输入参数映射:输入的参数类型可以是集合类型、基本数据类型或类类型
输出结果映射:输出结果可以是集合类型、基本数据类型或类类型
三.Mybatis映射文件和配置文件
配置文件:
配置了mybatis的运行环境和数据库连接信息等
<configuration>
:所有的配置信息都写在该标签中
<typeAliases>
:类型的别名
子标签:
<typeAliase>
:
属性:
- type:代表要给哪个类型起别名
- alias:别名
<package
>:<typeAliases>
子标签,作用是给包下所有的类都起别名,别名是类的类名
属性:
- name:包的名称
起别名后,在mapper文件中parameterType的值为类类型时,可用别名替代
<environments>
:用于配置数据库环境信息,可配置多个数据库
属性:
- default:表示默认环境
值为development:表示数据库环境为开发环境
值为test:表示数据库环境为测试环境
值为produce表示数据库环境为生产环境
<environment>
:配置其中的一个数据库环境
属性:
- id:数据库环境的唯一标识
<transactionManager>
:配置事务管理器
属性:
- type:事务管理类型(表示采用哪种类型的事务管理器)值:JDBC或MANAGER
属性的值:
- JDBC:JdbcTransactionFactory类创建TransactionManager,开发人员自己手动去管理事务
- MANAGER:ManagedTransactionFactory类创建事务管理器TransactionManager,让具备事务管理的服务器去管理事务。
<dataSource>
:配置数据源
属性:
- type:数据源类型
属性的值:
- POOLED:在与数据库连接之前会创建数据库连接池去产生连接
- UNPOOLED:每连接一次数据库都会创建一个新的连接,使用完了就会关闭
- JNDI:从Web服务器中获取数据源
<property>
:配置数据库基本信息
属性:
- name
- value
<mappers>
:映射器,告诉mybatis映射文件位置。加载配置文件时会加载映射文件
子标签:
<mapper>
:其中一个映射文件
属性:
- resource:映射文件的路径(路径之间是/)
映射文件:
配置了操作数据库的SQL语句,映射文件需要在配置文件中加载,每个映射文件对应数据库中的一张表。
<mapper>
:所有的SQL语句都写在该标签中
属性:
- namespace:映射文件的唯一标识,值为映射文件的全限定名。
<update>
: 建表和修改标签
作为建表时:
(1)属性:
- id:唯一标识,与映射接口中方法名相同。没映射接口可随便起
(2)SQL语句:与建表语句相同
作为修改时:
(1)属性:
- id
- parameterType:参数的类型
(2)SQL语句:
update 表名 set 列名1 = #{属性1},列名2 = #{属性2},列名3 = #{属性3} where 主键列列名 = #{对应属性}
<insert>
: 添加标签
(1) 属性:
- id: 同上标签
- parameterType:参数的类型,若为基本类型,该属性可省略不写。若为类类型,属性值为类全限定名。
映射接口中方法为insert(User user),则 parameterType值为User的全类名
(2)SQL语句:
insert into 表名 values(#{属性1},#{属性2},#{属性3},#{属性4})
"#{}"表示一个占位符,相当于?
{ }中是类的属性名,不是表的字段名
<delete>
: 删除标签
(1) 属性:
- id:同上标签
- parameterType:同上标签
(2)SQL语句:
delete from 表名 where 主键列列名 = #{对应属性名}
where后的是表的列名,{ }里是类的属性名
<select>
:查询标签
属性:
- id
- resultType:查询出的结果的类型
resultType和resultMap的区别:
- 使用select查询出来的列名和属性名一致,使用resultType,mybatis会把对应列名的值赋值给相同名字的属性。
- 使用select查询出来的列名和属性名不一致,使用resultMap,在select 语句前先定义resultMap。
- 若查询出的结果为基本数据类型,如查询数据条数,只能用resultType
<resultMap>
:结果的映射集
属性:
- type:代表将查询出来的数据封装成什么类型的对象
- id:resultMap的唯一标识
子标签:
(1)<id>
:主键列
- column:查询出来的列名
- property:
<resultMap
>:标签type里的属性名
<id column="ids" property="id"/>
表示将列ids的值赋给查询出的对象里的属性id
(2)<result>
:非主键列
属性:同上
<sql>
:封装sql语句的一部分,以便于反复使用
属性:
- id:封装的唯一标识
<include>
:用于引入
属性:
- refid:表示引入的是哪个sql,值为sql的id值
测试类
1.读取配置文件到内存中:
InputStream stream = Resources.getResourceAsStream(“配置文件名.xml”);
2.通过工厂加载配置文件内容
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
3.创建数据库连接并打开一个数据库会话
SqlSession sqlSession = sqlSessionFactory.openSession();
4.执行SQL语句
(1)sqlSession执行SQL语句
(2)映射接口的对象执行SQL语句
方法一:通过SqlSession执行SQL语句
导入包:
日志文件:
log4j.rootLogger=debug, stdout
log4j.logger.org.mybatis.example.BlogMapper=debug
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
实体类:
@AllArgsConstructor:创建有参构造器
@NoArgsConstructor:创建无参构造器
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int id;
private String name;
private int age;
private Date birthday;
}
映射文件:
<?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">
<!-- 所有sql语句都写在该标签中 -->
<mapper namespace="com.mybatis.mapper.StudentMapper">
<update id="createTable">
create table student(
id number primary key,
name varchar2(255),
age number,
birthday date
)
</update>
<insert id="insertData" parameterType="com.mybatis.bean.Student">
insert into student values(#{id},#{name},#{age},#{birthday})
</insert>
</mapper>
配置文件:
<?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"></transactionManager>
<!-- 配置数据源 -->
<dataSource type="POOLED">
<!-- 配置数据库基本信息 -->
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1522:XE"/>
<property name="username" value="jy"/>
<property name="password" value="jy"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 映射文件的位置 -->
<mapper resource="com/mybatis/mapper/StudentMapper.xml"></mapper>
</mappers>
</configuration>
数据库为mysql的配置文件:
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mydatabase?useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
测试类:
public class MybatisTest {
@Test
public void testTable() {
try {
//读取配置文件到内存中
InputStream stream = Resources.getResourceAsStream("mybatis-config.xml");
/*
* 通过工厂加载配置文件内容
*/
//获取的是默认的数据源
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
//获取其他数据源,写上数据源的唯一标识
//SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream, "test");
//SqlSessionFactory创建SqlSession
/*
sqlSession代表了与数据库的一个会话
只要能够得到会话对象,就说与数据库建立了连接
通过该对象也可以去执行sql语句
*/
SqlSession session = sqlSessionFactory.openSession();
//执行文件中的SQL语句
session.update("com.mybatis.mapper.StudentMapper.createTable");
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testInsert() {
try {
InputStream stream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
SqlSession session = sqlSessionFactory.openSession();
//添加一个用户
Student student = new Student();
student.setId(1);
student.setName("王亮");
student.setAge(23);
student.setBirthday(new Date());
session.insert("com.mybatis.mapper.StudentMapper.insertData", student);
//提交事务
session.commit();
} catch (IOException e) {
e.printStackTrace();
}
}
}
方法二:通过映射接口执行SQL语句
实体类同上
映射接口:
public interface StudentMapper {
//添加学生
void insert(Student student);
}
映射文件:
<?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">
<!-- 所有sql语句都写在该标签中 -->
<mapper namespace="com.mybatis.mapper.StudentMapper">
<!-- id为接口的方法名 -->
<insert id="insert" parameterType="com.mybatis.bean.Student">
insert into student values(#{id},#{name},#{age},#{birthday})
</insert>
</mapper>
配置文件同上
测试类:
public class MybatisTest {
@Test
public void testInsert() {
try {
InputStream stream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
SqlSession session = sqlSessionFactory.openSession();
//添加一个用户并赋值
Student student = new Student(2,"王刚",23,new Date());
//传入一个接口,就会返回该接口的实现类对象
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
//实现类对象会去执行sql语句
studentMapper.insert(student);
//提交事务
session.commit();
} catch (IOException e) {
e.printStackTrace();
}
}
}
四.Mybatis实现增删改查
实例:
日志文件同上
建表语句:
create table “user”(
2 u_id number primary key,
3 u_name varchar2(30),
4 u_gender varchar2(20),
5 u_age number);
注意:user为关键字,如果不加引号会显示表名无效
实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String gender;
private int age;
}
映射接口:
public interface UserMapper {
void add(User user);
void getAutoId(int id);
void delete(int id);
void update(User user);
void deleteAll();
User selectById(int id);
List<User> selectAll();
//查询数量
int selectCount();
}
数据源文件:
jdbc.driverClass=oracle.jdbc.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1522:xe
jdbc.username=jy
jdbc.password=jy
配置文件:
<?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>
<!-- 导入外部properties文件 -->
<properties resource="dataSource.properties"></properties>
<!-- 给类型起别名 -->
<typeAliases>
<!-- 给包下所有的类起别名 -->
<package name="com.mybatis.bean"/>
</typeAliases>
<!-- 配置数据库环境 -->
<environments default="development">
<environment id="development">
<!-- 配置事务管理器 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源 -->
<dataSource type="POOLED">
<!-- 配置数据库基本信息 -->
<property name="driver" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 映射文件的位置 -->
<mapper resource="com/mybatis/mapper/UserMapper.xml"></mapper>
</mappers>
</configuration>
映射文件
<?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.mybatis.mapper.UserMapper">
<insert id="add" parameterType="user">
insert into "user" values(#{id},#{name},#{gender},#{age})
</insert>
<!-- 如果参数类型时基本数据类型 paramType可不写 -->
<delete id="delete">
delete from "user" where u_id = #{id}
</delete>
<update id="update" parameterType="user">
update "user" set u_name = #{name},u_gender = #{gender},u_age = #{age} where u_id = #{id}
</update>
<delete id="deleteAll">
delete from "user"
</delete>
<!-- 定义resultMap,type:查询出结果封装成的类型 -->
<resultMap type="user" id="userResultMap">
<!-- id:主键列,column:列名,property:属性名 -->
<id column="u_id" property="id"/>
<!-- result:非主键列 -->
<result column="u_name" property="name"/>
<result column="u_gender" property="gender"/>
<result column="u_age" property="age"/>
</resultMap>
<!-- 封装 -->
<sql id="col">
u_id,u_name,u_gender,u_age
</sql>
<select id="selectById" resultMap="userResultMap">
select <include refid="col"></include> from "user" where u_id = #{id}
</select>
<select id="selectAll" resultMap="userResultMap">
select <include refid="col"></include> from "user"
</select>
<!-- 返回值类型是基本类型时,只能用resultType -->
<select id="selectCount" resultType="int">
select count(*) from "user"
</select>
</mapper>
注意:因为user是关键字,所以SQL语句中user需要加引号。如果表名不是关键字,不需要加引号
工具类:
/**
* 获得sqlSession的工具类
*/
public class SqlSessionUtil {
public static SqlSessionFactory sqlSessionFactory;
static {
try {
InputStream stream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
} catch (IOException e) {
e.printStackTrace();
}
}
//事务手动提交
public static SqlSession openSqlSession() {
return openSqlSession(false);
}
//事务自动提交
public static SqlSession openSqlSession(boolean auto) {
SqlSession sqlSession = sqlSessionFactory.openSession(auto);
return sqlSession;
}
}
测试类:
public class UserTest {
@Test
public void addUser() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//mapper.add(new User(11,"张三","男",22));
mapper.add(new User(14,"刘丽","女",20));
sqlSession.commit();
sqlSession.close();
}
@Test
public void deleteUser() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.delete(12);
sqlSession.close();
}
@Test
public void updateUser() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.update(new User(14,"莉莉丝","女",21));
sqlSession.close();
}
@Test
public void selectUser() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.selectById(13);
System.out.println(user);
sqlSession.close();
}
@Test
public void selectAll() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.selectAll();
users.forEach(System.out::println);
}
@Test
public void selectCount() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int count = mapper.selectCount();
System.out.println(count);
}
}