MyBatis本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。MyBatis是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
简单来说,MyBatis是一个用来帮你管理数据增删改查的框架。
配置文件pom.xml写上
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<!--修改Language level-->
<!--这里写你的jdk版本,如果是8则写1.8-->
<source>11</source>
<!--修改Java Compiler-->
<target>11</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<!-- 由于maven只能识别resources里的xml配置文件.因此放在mapper类中的配置文件需要设置<include>才能被获取 -->
<include>**/*.xml
org.mybatis
mybatis
3.4.5
mysql
mysql-connector-java
8.0.20
org.projectlombok
lombok
1.18.6
provided
新建mybatis数据库,并且在mybatis中新建一个空表t_account。
use mybatis;
create table t_account(
id int primary key auto_increment;
username varchar(11);
password varchar(11);
age int
)
package com.southwind.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account {
//成员变量要和数据库字段相同
private long id;
private String username;
private String password;
private int age;
}
config.xml位于resources文件下, 需要自己新建。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置mybatis运行环境-->
<environments default="development">
<environment id="development">
<!-- 配置JDBC事务管理-->
<transactionManager type="JDBC"></transactionManager>
<!-- POOLED配置JDBC数据源连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<!-- value="jdbc:mysql:// serverTimezone=GMT%2B8&-->
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8"></property>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
</configuration>
原理图:
1、创建Mapper类对应的Mapper.xml,定义管理该对象的SQL。(实际开发中,会给每个实体类创建对应的想xml文件)
<?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">
<!-- namespace设置为xml所在的包+文件名-->
<mapper namespace="com.southwind.mapper.AccountMapper">
<!-- 根据对象传参数-->
<!-- insert标签代表插入数据,还有delete,update和select;
根据id的值来调用方法执行sql语句;
parameterType是指调用对应方法时参数的数据类型;
-->
<insert id="save" parameterType="com.southwind.entity.Account">
insert into t_account(username,password,age) values (#{username},#{password},#{age})
</insert>
</mapper>
2、在全局配置文件config.xml中注册AccountMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置mybatis运行环境-->
<environments default="development">
<environment id="development">
<!-- 配置JDBC事务管理-->
<transactionManager type="JDBC"></transactionManager>
<!-- POOLED配置JDBC数据源连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<!-- value="jdbc:mysql:// serverTimezone=GMT%2B8&-->
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8"></property>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<!-- 注册AccountMapper.xml -->
<mappers>
<mapper resource="com\southwind\mapper\AccountMapper.xml"></mapper>
</mappers>
</configuration>
3、调用MyBatis的原生接口执行添加操作
package com.southwind.test;
import com.southwind.entity.Account;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
//忽视由于jdk版本过高导致的Illegal reflective access by org.apache.ibatis.reflection.Reflector警告
disableAccessWarnings();
//输入流文件 读取config配置
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
//获取实现接口
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//选择mapper里的
String statement = "com.southwind.mapper.AccountMapper.save";
Account account = new Account(1L,"张三","123",22);
sqlSession.insert(statement,account);
sqlSession.commit();
}
@SuppressWarnings("unchecked")
public static void disableAccessWarnings(){
try {
Class unsafeClass = Class.forName("sun.misc.Unsafe");
Field field = unsafeClass.getDeclaredField("theUnsafe");
field.setAccessible(true);
Object unsafe = field.get(null);
Method putObjectVolatile = unsafeClass.getDeclaredMethod("putObjectVolatile", Object.class, long.class, Object.class);
Method staticFieldOffset = unsafeClass.getDeclaredMethod("staticFieldOffset", Field.class);
Class loggerClass = Class.forName("jdk.internal.module.IllegalAccessLogger");
Field loggerField = loggerClass.getDeclaredField("logger");
Long offset = (Long) staticFieldOffset.invoke(unsafe, loggerField);
putObjectVolatile.invoke(unsafe, loggerClass, offset, null);
} catch (Exception ignored) {
}
}
}
4、结果
由于我们的AccountMapper类对应的Mapper.xml只有一个insert方法,并且inset的对象是Account(1L,“张三”,“123”,22),因此执行完后会在数据库中插入一行数据。
流程: 1、自定义接口,定义相关也二五方法
2、编写与方法对应的Mapper.xml
1、自定义接口
package com.southwind.repostory;
import com.southwind.entity.Account;
import java.util.List;
public interface AccountRepostory {
public int save(Account account);
public int update(Account account);
public int deleteById(long id);
public List<Account> findAll();
public Account findById(long id);
}
2、创建接口对应的mapper.xml,定义接口方法的sql语句。
mapper.xml中statement标签可根据sql执行的业务选择insert、update、delete和select
MyBatis框架会根据规则自动创建接口实现类的代理对象:
遵循的规则
<?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.southwind.repostory.AccountRepostory">
<!-- 插数据-->
<insert id="save" parameterType="com.southwind.entity.Account">
insert into t_account(username,password,age) values (#{username},#{password},#{age});
</insert>
<!--更新数据-->
<update id="update" parameterType="com.southwind.entity.Account">
update t_account set username = #{username},password = #{password},age = #{age} where id = #{id}
</update>
<!-- 根据id删除-->
<delete id="deleteById" parameterType="long">
delete from t_account where id = #{id}
</delete>
<!-- 根据id查找-->
<select id="findById" parameterType="long" resultType="com.southwind.entity.Account">
select * from t_account where id = #{id}
</select>
<!-- 查找所有-->
<select id="findAll" resultType="com.southwind.entity.Account">
select * from t_account
</select>
</mapper>
3、在config.xml中注册AccountRepository.xml
<!-- 注册AccountMapper.xml -->
<mappers>
<mapper resource="com\southwind\mapper\AccountMapper.xml"></mapper>
<mapper resource="com\southwind\repostory\AccountRepository.xml"></mapper>
</mappers>
4、调用接口的代理对象完成业务操作
package com.southwind.test;
import com.southwind.entity.Account;
import com.southwind.repostory.AccountRepostory;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;
public class Test2 {
public static void main(String[] args) {
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取实现接口的代理对象
AccountRepostory accountRepostory = sqlSession.getMapper(AccountRepostory.class);
//增加
// Account account = new Account(2L,"李四","726",25);
// accountRepostory.save(account);
//查找全部
// List list = accountRepostory.findAll();
// for(Account ac:list){
// System.out.println(ac);
// }
//修改
// Account account = accountRepostory.findById(2);
// account.setUsername("二狗");
// account.setAge(90);
// account.setPassword("111111");
// System.out.println(accountRepostory.update(account));
//删除
System.out.println(accountRepostory.deleteById(3));
//提交事务
sqlSession.commit();
//关闭资源
sqlSession.close();
}
}
Mapper.xml和config.xml是使用MyBatis框架的两大核心,所有操作都要通过这两个配置文件来配合完成。
1、基本数据类型
<select id="findById" parameterType="long" resultType="com.southwind.entity.Account">
select * from t_account where id = #{id}
</select>
2、String类型
<select id="findByName" parameterType="java.lang.String" resultType="com.southwind.entity.Account">
select * from t_account where username = #{username}
</select>
3、包装类
<select id="findById2" parameterType="java.lang.Long" resultType="com.southwind.entity.Account">
select * from t_account where id = #{id}
</select>
4、多个参数
<select id="findByNameAndAge" resultType="com.southwind.entity.Account">
select * from t_account where username = #{param1} and age =#{param2}
</select>
5、java Bean
<insert id="save" parameterType="com.southwind.entity.Account">
insert into t_account(username,password,age) values (#{username},#{password},#{age});
</insert>
<select id="count" resultType="int">
select count(id) from t_account
</select>
2、String类型
<select id="findById" resultType="java.lang.String">
select username from t_account where id = #{id}
</select>
3、包装类
<select id="count2" resultType="java.lang.Integer">
select count(id) from t_account
</select>
4、java Bean
<insert id="save" parameterType="com.southwind.entity.Account">
insert into t_account(username,password,age) values (#{username},#{password},#{age});
</insert>
例子:
student表和classes表:
表结构:主键:Classes的id,外键:student的cid
实体类:
Student类:
package com.southwind.entity;
import lombok.Data;
@Data
public class Student {
private int id;
private String name;
private Classes classes;
}
Classes类:
package com.southwind.entity;
import lombok.Data;
import java.util.List;
@Data
public class Classes {
private int id;
private String name;
private List<Student> students;
}
StudentRepository接口:
package com.southwind.repostory;
import com.southwind.entity.Student;
public interface StudentRepository {
public Student findById(int id);
}
StudentRepository.xml配置文件
实现一对多级联操作不用resultType,应该设置一个resultMap ,建立起Student和Classes的映射,然后传入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="com.southwind.repostory.StudentRepository">
<resultMap id="studentMap" type="com.southwind.entity.Student">
<!-- student映射-->
<id column="id" property="id"></id>
<result column="name" property="name"/>
<!-- 建立连接关系-->
<association property="classes" javaType="com.southwind.entity.Classes">
<id column="cid" property="id"></id>
<result column="cname" property="name"></result>
</association>
</resultMap>
<select id="findById" parameterType="int" resultMap="studentMap">
select s.id,s.name,c.id as cid,c.name as cname from student s , classes c where s.id = #{id};
</select>
</mapper>
ClassesRepository.xml配置文件
<?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.southwind.repostory.ClassesRepository">
<resultMap id="classesMap" type="com.southwind.entity.Classes">
<!-- student映射-->
<id column="cid" property="id"></id>
<result column="cname" property="name"/>
<!-- 建立连接关系
property是classes的成员变量
ofType是泛型
-->
<collection property="students" ofType="com.southwind.entity.Student">
<id column="id" property="id"/>
<result column="name" property="name" />
</collection>
</resultMap>
<select id="findById" parameterType="int" resultMap="classesMap">
select s.id,s.name,c.id as cid,c.name as cname from student s , classes c where c.id = #{id};
</select>
</mapper>
注意:resultmap需要根据两表的映射关系以及所需要查询的结果来设计
数据表:
三张,一张顾客表customer,一张商品表goods,一张映射表customer_goods,映射顾客与商品之间的对应关系。
package com.southwind.entity;
import lombok.Data;
import java.util.List;
@Data
public class Customer {
private int id;
private String name;
private List<Goods> goods;
}
Goods类
package com.southwind.entity;
import lombok.Data;
import java.util.List;
@Data
public class Goods {
private int id;
private String name;
private List<Customer> customers;
}
CustomerRepository接口
package com.southwind.repository;
import com.southwind.entity.Customer;
public interface CustomerRepository {
public Customer findById(int id);
}
CustomerRepository.xml配置文件
<?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.southwind.repository.CustomerRepository">
<resultMap id="customerMap" type="com.southwind.entity.Customer">
<!-- student映射-->
<id column="cid" property="id"></id>
<result column="cname" property="name"/>
<!-- 建立连接关系-->
<collection property="goods" ofType="com.southwind.entity.Goods">
<id column="gid" property="id"></id>
<result column="gname" property="name"></result>
</collection>
</resultMap>
<select id="findById" parameterType="int" resultMap="customerMap">
select c.id cid,c.name cname,g.id gid,g.name gname from customer c,goods g,customer_goods cg where c.id = #{id} and cg.cid = c.id and cg.gid = g.id;
</select>
</mapper>
GoodsRepository接口
package com.southwind.repository;
import com.southwind.entity.Customer;
import com.southwind.entity.Goods;
public interface GoodsRepository {
public Goods findById(int id);
}
GoodsRepository.xml配置文件
<?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.southwind.repository.GoodsRepository">
<resultMap id="goodsMap" type="com.southwind.entity.Goods">
<!-- student映射-->
<id column="gid" property="id"></id>
<result column="gname" property="name"/>
<!-- 建立连接关系-->
<collection property="customers" ofType="com.southwind.entity.Customer">
<id column="cid" property="id"></id>
<result column="cname" property="name"></result>
</collection>
</resultMap>
<select id="findById" parameterType="int" resultMap="goodsMap">
select c.id cid,c.name cname,g.id gid,g.name gname from customer c,goods g,customer_goods cg where g.id = #{id} and cg.cid = c.id and cg.gid = g.id;
</select>
</mapper>
目的:1、在查询顾客时根据映射表查出他购买的商品 2、在查询商品时根据映射表查出商品对应的买家
原理:在顾客类和商品类中都有一个集合,顾客类中是泛型为商品的集合,商品类则是泛型为顾客
因此在xml中要使用collection标签,并且根据他们的映射关系以及sql语句配置好xml文件
流程:1、确定sql语句 2、确定映射关系 3、写配置文件xml
查询结果:(以查询商品为例)
控制台输出:
Goods(id=3, name=洗衣机, customers=[Customer(id=1, name=张三, goods=null), Customer(id=3, name=小明, goods=null)])
MyBatis框架需要实体类、自定义Mapper接口,Mapper.xml
传统开发中以上三个都需要开发者手动创建,逆向工程可以实现自动创建。
使用:
通过MyBatis Generator(简称MBG,是一个代码生成器)
1、新建maven工程
创建依赖
<?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.southwind</groupId>
<artifactId>aimbg</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<!--修改Language level-->
<!--这里写你的jdk版本,如果是8则写1.8-->
<source>11</source>
<!--修改Java Compiler-->
<target>11</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<!-- 由于maven只能识别resources里的xml配置文件.因此放在mapper类中的配置文件需要设置<include>才能被获取 -->
<include>**/*.xml
org.mybatis
mybatis
3.5.4
mysql
mysql-connector-java
8.0.20
org.mybatis.generator
mybatis-generator-core
1.4.0
2、创建MBG配置文件generatorConfig.xml
位于resource文件下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="testTables" targetRuntime="MyBatis3">
<!-- jdbc连接-->
<jdbcConnection
driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8"
userId="root" password="1234"
></jdbcConnection>
<!-- 实体类生成-->
<javaModelGenerator targetPackage="com.southwind.entity" targetProject="./src/main/java"></javaModelGenerator>
<!-- sql语句-->
<sqlMapGenerator targetPackage="com.southwind.repository" targetProject="./src/main/java"></sqlMapGenerator>
<!-- map接口-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.southwind.repository" targetProject="./src/main/java"></javaClientGenerator>
<table tableName="t_account" domainObjectName="Account"></table>
</context>
</generatorConfiguration>
3、创建Generator执行类
package com.southwind.test;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> warings = new ArrayList<String>();
boolean overwrite = true;
String genCig = "/generatorConfig.xml";
File configFile = new File(Main.class.getResource(genCig).getFile());
ConfigurationParser configurationParser = new ConfigurationParser(warings);
Configuration configuration = null;
try {
configuration = configurationParser.parseConfiguration(configFile);
} catch (IOException e) {
e.printStackTrace();
} catch (XMLParserException e) {
e.printStackTrace();
}
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = null;
try {
myBatisGenerator = new MyBatisGenerator(configuration,callback,warings);
} catch (InvalidConfigurationException e) {
e.printStackTrace();
}
try {
myBatisGenerator.generate(null);
} catch (SQLException throwables) {
throwables.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
执行后会自动创建实体类、Mapper接口以及Mapper配置文件。
延迟加载是指对数据持久层的操作,对于多个sql的查询,采取延迟加载的方式来减少与数据库的交互。
在访问学生表和班级表时,假如只需要获取学生表的信息,不需要获取学生对应的班级时就可以不执行查询班级表的SQL语句。
<settings>
<!-- 打印sql-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
StudentRepository
public Student findByIdLazy(int id);
StudentRepository.xml
<resultMap id="studentMapLazy" type="com.southwind.entity.Student">
<id column="id" property="id"></id>
<result column="name" property="name"/>
<association property="classes" javaType="com.southwind.entity.Classes"
select="com.southwind.repository.ClassesRepository.findByIdLazy"
column="cid">
</association>
</resultMap>
<select id="findByIdLazy" parameterType="int" resultMap="studentMapLazy">
select * from student where id = #{id};
</select>
ClassesRepository
public Classes findByIdLazy(int id);
ClassesRepository.xml
<select id="findByIdLazy" parameterType="int" resultType="com.southwind.entity.Classes">
select * from classes where id = #{id}
</select>
使用缓存减少java应用与数据库的交互次数,从而提高程序的运行效率。会将之前查找的对象存放在缓存中,下次查找相同对象就可以直接访问,而不需要再与数据库交互。
MyBatis缓存分类
创建SqlSession对象,对象中有HashMap用于存储缓存数据。不同的SqlSession之间的缓存数据互不影响。
一级缓存的作用域是SqlSession范围的,在同一个SqlSession中执行两次相同的sql语句,第一次执行完会把结果保存到缓存中,第二次查询直接从缓存中调取。
注意:如果SqlSession执行了DML操作(insert、update、delete),那么需要清空缓存以保证数据的准确性
对于使用同一个Mapper的多个SqlSession,会使用同一个缓存区,同样也是使用HashMap进行数据存储。与一级缓存比较,二级缓存范围更大。
二级缓存的作用域是Mapper的同一个namespace,不同的SqlSession执行相同的namespace下的sql语句时可以根据二级缓存获得已查询过的信息。
(1)MyBatis自带二级缓存
<settings>
<!-- 打印sql-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
<cache></cache>
implements Serializable
package com.southwind.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account implements Serializable {
//成员变量要和数据库字段相同
private long id;
private String username;
private String password;
private int age;
}
package com.southwind.test;
import com.southwind.entity.Account;
import com.southwind.repository.AccountRepository;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
public class Test4 {
public static void main(String[] args) {
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
AccountRepository accountRepository = sqlSession.getMapper(AccountRepository.class);
Account account = accountRepository.findById(1);
System.out.println(account);
//关闭sqlSession 模拟两个sqlSession进行同个查询,观察执行了多少次sql语句
//一级缓存会执行两次,二级缓存只会执行一次
sqlSession.close();
sqlSession = sqlSessionFactory.openSession();
accountRepository = sqlSession.getMapper(AccountRepository.class);
Account account1 = accountRepository.findById(1);
System.out.println(account1);
}
}
(2)ehcache
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.4.3</version>
</dependency>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore/>
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
<settings>
<!-- 打印sql-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
<cache type="org.mybatis.caches.ehcache.EhcacheCache">
<!-- 缓存创建后,最后一次访问缓存的时间到缓存失效的时间间隔-->
<property name="timeToIdleSeconds" value="3600"/>
<!-- 缓存自创建时间起到失效的时间间隔-->
<property name="timeToLiveSeconds" value="3600"/>
<!-- 缓存回收策略,LRU表示移除近期使用最少的对象-->
<property name="memoryStoreEvictionPolicy" value="LRU'"/>
</cache>
package com.southwind.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account {
//成员变量要和数据库字段相同
private long id;
private String username;
private String password;
private int age;
}
where标签一般和if搭配使用,where标签可以自动判断是否要删除多余的and关键字,如果检测到where直接和and拼接,则自动删除and。
<select id="findByAccount" parameterType="com.southwind.entity.Account" resultType="com.southwind.entity.Account">
select * from t_account
<where>
<if test="id!=0">
id = #{id}
</if>
<if test="username!=null">
and username = #{username}
</if>
<if test="password!=null">
and password = #{password}
</if>
<if test="age!=0">
and age = #{age}
</if>
</where>
</select>
<select id="findByAccount" parameterType="com.southwind.entity.Account" resultType="com.southwind.entity.Account">
select * from t_account
<where>
<choose>
<when test="id!=0">
id = #{id}
</when>
<when test="username!=null">
username = #{username}
</when>
<when test="password!=null">
password = #{password}
</when>
<when test="age!=0">
age = #{age}
</when>
</choose>
</where>
</select>
trim标签中的prefix和suffix属性会被用于生成实际的sql语句,会和标签内部的语句进行拼接,如果语句前后出现了prefixOverrides或者suffixOverrides属性中指定的值,MyBatis框架会自动将其删除。
prefix:在trim标签内sql语句加上前缀
suffix:在trim标签内sql语句加上后缀
suffixOverrides:指定去除多余的后缀内容
比如:suffixOverrides=”,”,去除trim标签内sql语句多余的后缀”,”
prefixOverrides:指定去除多余的前缀内容
<select id="findByAccount" parameterType="com.southwind.entity.Account" resultType="com.southwind.entity.Account">
select * from t_account
<trim prefix="where" prefixOverrides="and">
<if test="id!=0">
id = #{id}
</if>
<if test="username!=null">
and username = #{username}
</if>
<if test="password!=null">
and password = #{password}
</if>
<if test="age!=0">
and age = #{age}
</if>
</trim>
</select>
set标签用于update操作,会自动根据参数选择生成sql语句。
<update id="update" parameterType="com.southwind.entity.Account">
update t_account
<set>
<if test="username!=null">
username = #{username},
</if>
<if test="password!=null">
password = #{password},
</if>
<if test="age!=0">
age = #{age},
</if>
</set>
where id = #{id}
</update>
foreach标签迭代生成一系列值,这标签主要用于sql的in语句。
<select id="findByIds" parameterType="com.southwind.entity.Account" resultType="com.southwind.entity.Account">
-- select * from t_account where id in (2,4);
select * from t_account
<where>
<foreach collection="ids" open="id in (" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>