MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
Mybatis中文文档 : http://www.mybatis.org/mybatis-3/zh/index.html
GitHub:https://github.com/mybatis/mybatis-3
持久化是将程序数据在持久状态和瞬时状态间转换的机制。
Mybatis就是帮助程序猿将数据存入数据库中,和从数据库中取数据。传统的jdbc操作,有很多重复代码块。比如:数据取出时的封装,数据库的建立连接等等…,通过框架可以减少重复代码,提高开发效率。
MyBatis 是一个半自动化的ORM框架 (Object Relationship Mapping,对象关系映射),所有的事情,不用Mybatis依旧可以做到,只是用了它,所有实现会更加简单!
MyBatis的优点:
mybatis主要有两种实现方式,一种是通过配置文件实现,另一种是通过注解的方式实现。
CREATE DATABASE `mybatis`;
USE `mybatis`;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`id` int(20) NOT NULL, `username` varchar(20) DEFAULT NULL,
`pwd` varchar(40) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `user`(`id`,`username`,`pwd`) values (1,'xiaoming','123456'),(2,'张三','2345678'),(3,'李四','3456789');
<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.0modelVersion>
<groupId>com.yuangroupId>
<artifactId>note_mybaties_01artifactId>
<version>1.0-SNAPSHOTversion>
<packaging>jarpackaging>
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.5version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.10version>
<scope>testscope>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.6version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.12version>
dependency>
dependencies>
<build>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>truefiltering>
resource>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>truefiltering>
resource>
resources>
build>
project>
路径com/lyl/entity/User.java
package com.lyl.entity;
import java.io.Serializable;
import java.util.Date;
@Data
public class User implements Serializable{
private Integer id;
private String username;
private String pwd;
}
路径com/lyl/dao/UserDao.java
package com.lyl.dao;
import com.lyl.entity.User;
import java.util.List;
/**
* 用户的持久层接口
*/
public interface UserDao {
List<User> findAll();
}
路径:resources/lyl/dao/UserDao.xml
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lyl.dao.UserDao">
<select id="findAll" resultType="com.lyl.entity.User">
SELECT * FROM USER
select>
mapper>
路径:resources/SqlMapConfig .xml
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">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///数据库名"/>
<property name="username" value="数据库账户"/>
<property name="password" value="数据库密码"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/lyl/dao/UserDao.xml"/>
mappers>
configuration>
数据库也可以通过如下方式配置:
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
properties>
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<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="com/lyl/dao/UserDao.xml"/>
mappers>
configuration>
package com.lyl.test;
import com.lyl.dao.UserDao;
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;
public class UserDaoTest {
InputStream is = null;
SqlSessionFactory factory = null;
SqlSession session = null;
@Before
public void init() throws IOException {
//读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建会话工厂
factory = new SqlSessionFactoryBuilder().build(is);
//生产SQLSession对象
session = factory.openSession();
}
@After
public void close() throws IOException {
session.commit();
session.close();
is.close();
}
@Test
public void findAllTest(){
UserDao userDao = session.getMapper(UserDao.class);
System.out.println(userDao.findAll());
}
}
namespace:namespace中的包名要和Dao/Mapper接口的包名一致!
<insert id="addUser" parameterType="com.lyl.entity.User">
insert into mybatis.user (id, username, pwd) values (#{id},#{username},#{pwd});
insert>
<update id="updateUser" parameterType="com.lyl.entity.User">
update mybatis.user set username=#{username},pwd=#{pwd} where id = #{id} ;
update>
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id = #{id};
delete>
注意:
session = factory.openSession(true);
与3.1.2相同
与3.1.3相同
package com.lyl.dao;
import com.lyl.entity.User;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* 用户的持久层接口
*/
public interface UserDao {
@Select("SELECT * FROM USER")
List<User> findAll();
}
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">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///数据库名"/>
<property name="username" value="数据库账户"/>
<property name="password" value="数据库密码"/>
dataSource>
environment>
environments>
<mappers>
<mapper class="com.lyl.dao.UserDao"/>
mappers>
configuration>
同3.1.8相同
#{}
是预编译处理,${}
是字符串替换。
#{}
是 sql 的参数占位符,MyBatis 会将 sql 中的#{}
替换为?
号,在 sql 执行前会使用 PreparedStatement 的参数设置方法,按序给 sql 的? 号占位符设置参数值,比如 ps.setInt(0, parameterValue),#{item.name}
的取值方式为使用反射从参数对象中获取 item 对象的 name 属性值,相当于 param.getItem().getName()。${}
是 Properties 文件中的变量占位符,它可以用于标签属性值和 sql 内部,属于静态文本替换,比如${driver}
会被静态替换为com.mysql.jdbc. Driver
。使用了同步代码快保障了每一个线程拿到的是不同的连接,是一个线程安全的集合。
主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。
//生产SQLSession对象 session = factory.openSession(true);
//它是通过sqlsession对象的commit方法和rollback方法实现事务的提交和回滚
session.commit();
session.close();
<where>
<if>
<foreach>
这是一个根据条件查询的语句,但是条件有可能有,也有可能没有,就要使用动态SQL标签了[ids是Vo类里的属性名]
<include><sql id="defUser"> SELECT * FROM USER sql>
<select id="findUserIn" resultType="User" parameterType="QueryVo">
<include refid="defUser"/>
<where>
<if test="#{ids!= null and ids.size > 0 }">
id in
<foreach collection="ids " open="(" close=")" item="id" separator=",">
#{id}
foreach>
if>
where>
select>
@Insert
:实现新增
@Update
:实现更新
@Delete
:实现删除
@Select
:实现查询
@Result
:实现结果集封装
@Results
:可以与@Result 一起使用,封装多个结果集
@ResultMap
:实现引用@Results 定义的封装
@One
:实现一对一结果集封装
@Many
:实现一对多结果集封装
@SelectProvider
: 实现动态 SQL 映射
@CacheNamespace
:实现注解二级缓存的使用
@Results
注解代替的是标签
, 该注解中可以使用单个@Result 注解,也可以使用@Result 集合 @Results({@Result(),@Result()})或@Results(@Result())
@Resutl
注解代替了
标签和
标签 , @Result 中 属性介绍:
@One
注解(一对一)
代替了
标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
@One 注解属性介绍:
@Many
注解(多对一), 代替了
标签, 是多表查询的关键,在注解中用来指定子查询返回对象集合。
注意: 聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType (一般为 ArrayList)但是注解中可以不定义;
使用格式: @Result(property="",column="",many=@Many(select=""))
<resultMap id="accountUserMap" type="account">
<id property="id" column="id"/>
<result property="uid" column="uid"/>
<result property="money" column="money"/>
<association
property="users"
column="uid"
javaType="user"
select="com.yuan.dao.UserDao.findById"
/>
resultMap>
<select id="findAll" resultMap="accountUserMap">
SELECT * FROM ACCOUNT
select>
<resultMap id="userAccountMap" type="user">
<id property="id" column="id">id>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<collection
property="accounts"
column = "id"
select="com.yuan.dao.AccountDao.findByUid"
ofType="account"/>
resultMap>
<select id="findAll" resultMap="userAccountMap">
SELECT * FROM USER
select>
像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提 高性能。 Mybatis 中缓存分为一级缓存,二级缓存。
一级缓存指的是Mybatis中SqlSession对象的缓存。
当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。该区域的结构是一个Map。当我们再次查询同样的数据时,mybatis会先去sqlsession中查询是否有该数据,有的话直接拿出来用。当SqlSession对象消失时,mybatis的一级缓存也就消失了。
一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在,默认是开启的。当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。
二级缓存指的是Mybatis中SqlSessionFactory对象的缓存。 由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
二级缓存(默认开启)的使用步骤:
<settings>
<setting name="cacheEnabled" value="true"/>
settings>
【在映射文件中添加了这个标签就完事了】注意: 当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,这种就可以使用序列化方式来保存对象。
第一步: 配置文件开启二级缓存
第二步: 在接口文件接口名上添加注解@CacheNamespace(blocking = true)