1 什么是mybatis
MyBatis 本是apache的⼀个开源项⽬iBatis, 2010年这个项⽬由apache software foundation 迁移
到了google code,并且改名为MyBatis 。2013年11⽉迁移到Github。
iBATIS⼀词来源于"internet"和"abatis"的组合,是⼀个基于Java的持久层框架。iBATIS提供的持久
层框架包括SQL Maps和Data Access Objects(DAOs)
MyBatis 是⼀款优秀的持久层框架,它⽀持定制化 SQL、存储过程以及⾼级映射。MyBatis 避免了
⼏乎所有的 JDBC 代码和⼿动设置参数以及获取结果集。MyBatis 可以使⽤简单的 XML 或注解来配置和
映射原⽣信息,将接⼝和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的
记录。
2搭建MYbatis
创建一个普通的maven项目,然后导入依赖包
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
</dependencies>
然后resource资源下新建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"> <!--环境的id-->
<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/student"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 指定maper⽂件的路径(maven项⽬从resources源⽂件夹下找资源)-->
<mappers>
<mapper resource="包名/mapper⽂件名"/>
</mappers>
</configuration>
新建一个类,接口,mapper,如图,
类,以及其他配置文件的源码,注意,类里的属性如下,类名和表名一致,属性和列名一致,不一致会报错,还有数据库里列的字段属性,要保持一致,不然很可能报SQLException错误,
代码结构如图
student类
package com.bean;
public class student {
private int studentid;
private String studentno;
private String stuname;
public student() {
}
public student(int studentid, String studentno, String stuname) {
this.studentid = studentid;
this.studentno = studentno;
this.stuname = stuname;
}
public int getStudentid() {
return studentid;
}
@Override
public String toString() {
return "student{" +
"studentid=" + studentid +
", studentno='" + studentno + '\'' +
", studname='" + stuname + '\'' +
'}';
}
public void setStudentid(int studentid) {
this.studentid = studentid;
}
public String getStudentno() {
return studentno;
}
public void setStudentno(String studentno) {
this.studentno = studentno;
}
public String getStudname() {
return stuname;
}
public void setStudname(String studname) {
this.stuname = studname;
}
}
pom.xml
<?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</groupId>
<artifactId>Mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
</dependencies>
</project>
dao接口
package com.dao;
import com.bean.student;
import java.util.List;
public interface studentDao {
//定义增删改查的方法
public List<student> getall();
}
测试类Test1
package com;
import com.bean.student;
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.IOException;
import java.io.Reader;
import java.util.List;
public class Test1 {
public static void main(String[] args) {
try {
//1加载配置文件
Reader reader=Resources.getResourceAsReader("mybatis.xml");
/* 2得到SQLSessionFactoryBuilder*/
SqlSessionFactoryBuilder builder =new SqlSessionFactoryBuilder();
SqlSessionFactory build =builder.build(reader);
//3得到SQLSession
SqlSession session=build.openSession();
//4操作sql
List<student> list =session.selectList("com.dao.studentDao.getall");//调取sql完整路径=namespace+id
//5遍历
for (student stu : list){
System.out.println(stu);
}
//6关闭资源
session.close();
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
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"> <!--环境的id-->
<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/student"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 指定maper⽂件的路径(maven项⽬从resources源⽂件夹下找资源)-->
<mappers>
<mapper resource="studentMapper.xml"/>
</mappers>
</configuration>
studnetMapper.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定义接口的完整路劲-->
<mapper namespace="com.dao.studentDao">
<select id="getall" resultType="com.bean.student">
select *from stud;
</select>
</mapper>
查询成功截图
mybatis的执行过程
1 先读取xml文件,指定数据库连接信息,和mapper,读取完之后连接,读取到mapper后就可以读取里边的对应关系,
2创建SQLsessionFactoryBuilder,
3就是上面代码里,利用selectList里边传值
4关闭打开的资源
配置多数据源
这个里边一种对应一种数据源,可以复制内容,下边可以配置多种数据源,如果要切换数据源,在这个里边添加第二个参数,另一个数据源的id值
CURD操作
1 单个基本类型参数或 String 类型:
mapper读取参数:#{参数名(也可以是⾃定义名称)}
修改如下操作
实现新增
如果此时提交到数据库里的是乱码的话,需要修改编码方式
添加多个值的时候用map集合
增加成功
在做查询时,如果需要将查询的结果和实体类属性⾃动对应的话,要求:属性名=列名
添加:session.insert(“namespace+id”[,传递给sql的参数值]);
修改:session.update(“namespace+id”[,传递给sql的参数值]);
删除:session.delete(“namespace+id”[,传递给sql的参数值]);
单⾏:session.selectOne(“namespace+id”[,传递给sql的参数值]);
多⾏:session.selectList(“namespace+id”[,传递给sql的参数值]);
处理多个聚合函数:使⽤map作为⽅法的返回值,默认key是列名
注意这里有些是只能传入一个值
注意:增删改的时候需要提交事务
session.commit();
//1.加载配置⽂件
Reader r=Resources.getResourceAsReader(“mybatis-config.xml”);
//2.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder= new SqlSessionFactoryBuilder();
//3.得到session⼯⼚
SqlSessionFactory factory=builder.build®;
//4.得到session
SqlSession session= factory.openSession();
//5.调取sql语句,insert(“⽅法的完整路径”),路径=namespace+id
int rs=session.insert(“dao.EmpDao.insertEmp”,e);
session.commit();
session.rollback();
查询的时候要添加resultType属性
getMapper调取方法
package com;
import com.bean.student;
import com.dao.studentDao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
public class TestDemo {
public static void main(String[] args) {
try {
//1,获取SQLSession对象
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSession session =new SqlSessionFactoryBuilder().build(reader).openSession();
//2得到要调用的方法
studentDao stuDao=session.getMapper(studentDao.class);//这里是一个反射的应用
List<student> studentList=stuDao.getall();//调用方法的全路径实现
for (student stu:studentList)
{
System.out.println(stu);
}
//3关闭资源
} catch (IOException e) {
e.printStackTrace();
}
}
}
ThreadLocal
普通存值实现线程共享,ThreadLocal实现线程独立
看如下代码:
package com;
import java.util.ArrayList;
import java.util.List;
public class TestThread {
private ThreadLocal<String> threadLocal=new ThreadLocal<>();
private List<String> list=new ArrayList<String >();
class A extends Thread{ /*基础Thread类重写里边的方法*/
@Override
public void run() {
/*存值*/
System.out.println("A 开始存值");
threadLocal.set("thread 内容");
list.add("list内容");
System.out.println("A--ThreadLocal="+threadLocal.get());
}
}
class B extends Thread{ /*基础Thread类重写里边的方法*/
@Override
public void run() {
/*取值*/
try {
Thread.sleep(2000);//为了避免未存值B线程就抢到了
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B开始取值");
System.out.println(threadLocal.get());
System.out.println(list.get(0));;
System.out.println("B--ThreadLocal="+threadLocal.get());
}
}
public static void main(String[] args) {
TestThread testThread =new TestThread();
TestThread.A a=testThread.new A();
TestThread.B b=testThread.new B ();
a.start();
b.start();
}
}
运行结果:
原理解释:
ThreadLocal并⾮是⼀个线程的本地实现版本,它并不是⼀个
Thread,⽽是threadlocalvariable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局
部变量(ThreadLocal)其实的功⽤⾮常简单,就是为每⼀个使⽤该变量的线程都提供⼀个变量值的副本,
是Java中⼀种较为特殊的线程绑定机制,是每⼀个线程都可以独⽴地改变⾃⼰的副本,⽽不会和其它线
程的副本冲突。
Thre优化SQLSession
package com.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.IOException;
import java.io.Reader;
public class SqlSessionUtil {
private static ThreadLocal<SqlSession> threadLocal=new ThreadLocal<SqlSession>();
private static SqlSessionFactory sqlSessionFactory;
static {
try {
Reader resourceReader= Resources.getResourceAsReader("mybatis.xml");
sqlSessionFactory=new SqlSessionFactoryBuilder().build(resourceReader);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSession(){ //单例模式
SqlSession session =threadLocal.get();
if (session==null){
session=sqlSessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
public static void closeSession(){
SqlSession session=threadLocal.get();
if(session!=null){
session.close();
threadLocal.remove();
}
}
}
给类起别名
为了简便
还可以指定包的路径
获得新增数据的id
在Mapper.xml配置文件中新增数据的后边加上上边的两个属性,表示将自动增加的id附到userid上去
Log4J日志
在mybatis里显示sql语句
首先添加依赖包
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
然后新建一个配置文件
log4j.properties
log4j.rootLogger=DEBUG, Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
log4j就是将日志信息打印出来,可以输出到控制台,文件数据库等
如图,进行插入一条信息以后,控制台打印出来对应的日志信息
mybatis的复杂查询
in查询
foreach标签中属性说明:
item 表示集合中每⼀个元素进⾏迭代时的别名,等同于c 标签中的var
index 指定⼀个名字,⽤于表示在迭代过程中,每次迭代到的位置,可以不写
open 表示该语句以什么开始,
separator 表示在每次进⾏迭代之间以什么符号作为分隔符,
close 表示以什么结束,
注意:在使⽤foreach 的时候最关键的也是最容易出错的就是collection 属性,
collection该属性是必须指定的
list 时取值list,数组时取值array,map 时取值map 的key 值
(1)参数是list
首先复制一份原来的mapper,做修改
<select id="finda" resultType="com.bean.student">
select *from stud where studentid in
<foreach collection="list" item="sid" open="(" close=")" separator=",">
#{sid}
</foreach>
</select>
然后定义一个新的接口
public List<student> finda(List list);
创建一个新的测试类
package com;
import com.bean.student;
import com.dao.studentDao2;
import com.util.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.ArrayList;
import java.util.List;
public class TestIN {
public static void main(String[] args) {
SqlSession session=SqlSessionUtil.getSession();
studentDao2 stuDao2=session.getMapper(studentDao2.class);
List list=new ArrayList();
list.add(1);
list.add(3);
list.add(5);
list.add(7);
List<student> students= stuDao2.finda(list);
for (student student : students) {
System.out.println(student);
}
SqlSessionUtil.closeSession();
}
}
运行成功
第二种方法使用数据进行遍历,只需要修改一下传值方式,并且collection里边改为array,
第三种方式,map集合。map集合不同于其他点的是map集合是以键值对来存储的,可以进行多个值的查询
同理,以上三种方法代码如下
mapper.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定义接口的完整路劲-->
<mapper namespace="com.dao.studentDao2">
<select id="finda" resultType="com.bean.student">
select *from stud where studentid in
<foreach collection="list" item="sid" open="(" close=")" separator=",">
#{sid}
</foreach>
</select>
<select id="findb" resultType="com.bean.student">
select *from stud where studentid in
<foreach collection="array" item="sid" open="(" close=")" separator=",">
#{sid}
</foreach>
</select>
<select id="findc" resultType="com.bean.student">
select *from stud where studentid in
<foreach collection="ids" item="sid" open="(" close=")" separator=",">
#{sid}
</foreach>
</select>
</mapper>
dao
package com.dao;
import com.bean.student;
import java.util.List;
import java.util.Map;
public interface studentDao2 {
//in 查询
public List<student> finda(List list);
public List<student> findb(int [] ids);
public List<student> findc(Map map)
;
}
Test
package com;
import com.bean.student;
import com.dao.studentDao2;
import com.util.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TestIN {
public static void main(String[] args) {
SqlSession session=SqlSessionUtil.getSession();
studentDao2 stuDao2=session.getMapper(studentDao2.class);
/* List list=new ArrayList();
list.add(1);
list.add(3);
list.add(5);
list.add(7);
List<student> students= stuDao2.finda(list);*/
//数组
/*int [] ids=new int[] {1,3,5,7};
List<student> students= stuDao2.findb(ids);
*/
//map
Map map=new HashMap();
List list=new ArrayList();
list.add(1);
list.add(3);
list.add(5);
list.add(7);
map.put("ids",list);
List <student> students=stuDao2.findc(map);
for (student student : students) {
System.out.println(student);
}
SqlSessionUtil.closeSession();
}
}
模糊查询
如果传递的参数是多个时?------使⽤Map 集合
模糊查询:
注意:test属性中读取属性值时直接写属性名
模糊查询读取属性时使el 表达式,${属性名}
除以上位置外,都使⽤#{属性名}
多个条件时使⽤and,or 拼接
如果传递过来的是map类型,则test属性中写的是key
#{}:相当于占位符
#{id}:其中的id可以表示输⼊参数的名称,如果是简单类型名称可以任意
${}:表示拼接sql语句
v
a
l
u
e
:
表
示
获
取
输
⼊
的
参
数
值
,
{value}:表示获取输⼊的参数值,
value:表示获取输⼊的参数值,{}会引起SQL注⼊,⼀般情况下不推荐使⽤。
示例:
Mapper.xml
<select id="findd" resultType="com.bean.student">
select *from stud where 1=1
<if test="stuname!=null and stuname !=''">
and stuname like "%"#{stuname}"%"
</if>
<if test="sno!=null and sno!=''">
and studentno=#{sno}
</if>
</select>
TestLike 类
package com;
import com.bean.student;
import com.dao.studentDao2;
import com.util.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TestLike {
public static void main(String[] args) {
SqlSession session=SqlSessionUtil.getSession();
studentDao2 stuDao2=session.getMapper(studentDao2.class);
Map map=new HashMap();
map.put("stuname","张");
map.put("sno","s1101");
List<student> students=stuDao2.findd(map);
for (student student : students) {
System.out.println(student);
}
}
}
Dao接口
public List<student> findd(Map map);
map和实体类的区别,传入的值是不一样的
student传入的是类的属性,必须和student里的属性名相同
区间查询
两种方法,一种是between and
另一种是 >= <= ,这里要注意的一点是注释的时候另一条语句移出去,我就是因为在同一个select下注释的导致半天没有找到错误在哪
现附上区间查询的代码
TestBetween 类
package com;
import com.bean.student;
import com.dao.studentDao2;
import com.util.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TestBetween {
public static void main(String[] args) {
SqlSession session=SqlSessionUtil.getSession();
studentDao2 stuDao2=session.getMapper(studentDao2.class);
Map map=new HashMap();
map.put("begin",1);
map.put("end",3);
List<student> students=stuDao2.findf(map);
for (student student : students) {
System.out.println(student);
}
SqlSessionUtil.closeSession();
}
}
mapper.xml类
<!-- select *from stud where studentid between #{begin} and #{end}-->
<select id="findf" resultType="com.bean.student">
select * from stud where studentid>=#{begin} and studentid <![CDATA[<=]]> #{end} <!--//这里因为<和里边重复,所以需要进行转移-->
</select>
dao接口的
resultMap处理列名不一致问题
查询结果映射
此处列名为stuage,但是在student中定义为age,列名不一样
resultMap可以自定义属性名和列名,方便操作
Test测试类
package com;
import com.bean.student;
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.IOException;
import java.io.Reader;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Test0 {
public static void main(String[] args) {
try {
//1加载配置文件
Reader reader=Resources.getResourceAsReader("mybatis.xml");
/* 2得到SQLSessionFactoryBuilder*/
SqlSessionFactoryBuilder builder =new SqlSessionFactoryBuilder();
SqlSessionFactory build =builder.build(reader);
//3得到SQLSession
SqlSession session=build.openSession();
//4操作sql
List<student> list = session.selectList("com.dao.studentDao.getall");
//5遍历
for (student student : list) {
System.out.println(student);
}
session.commit();//做完修改得需要提交事务
//6关闭资源
session.close();
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
age查询成功
多表查询
代码在下边整体附上
两表联查:⼀对多和多对⼀
注:如果是单表查询,select 中使⽤resultType 设置返回的类型即可
但是如果是多表联查,那么select 查询的结果需要单独使⽤resultMap 标签来
进⾏结果的映射
存的是集合的话使⽤Collection ⼦标签
存的是⼀⽅的话使⽤association ⼦标签
resultType 和resultMap 属性只能出现⼀个
遵循一个原则 :多方有一方的对象,一方有多方的集合
多对一
查询结果
多对一
查询学生信息以及对应的年及信息
查询成功
JavaType和ofType都是⽤来指定对象类型的,但是JavaType是⽤来指定pojo中属性的类型,⽽ofType指
定的是映射到list集合属性中pojo的类型。
多对多
一对一,注意这里千万不要有空格
空格引发的bug
mybatis分页
sql 语句只需要查询数据,不实现分⻚代码
⽅式1:
Mybatis使⽤RowBounds对象进⾏分⻚,它是针对ResultSet结果集执⾏的内存分⻚,⽽⾮物理分⻚。可
以在sql内直接书写带有物理分⻚的参数来完成物理分⻚功能,也可以使⽤分⻚插件来完成物理分⻚。
优缺点
物理分⻚每次都要访问数据库,逻辑分⻚只访问⼀次
物理分⻚占⽤内存少,逻辑分⻚相对较多
物理分⻚数据每次都是最新的,逻辑分⻚有可能滞后
实现内存分页
⽅式2:使⽤分⻚插件
分⻚插件的基本原理是使⽤Mybatis提供的插件接⼝,实现⾃定义插件,在插件的拦截⽅法内拦截待执⾏
的sql,然后重写sql,根据dialect⽅⾔,添加对应的物理分⻚语句和物理分⻚参数。
(a)导⼊jar 包
分⻚插件:pagehelper.jar
sql 解析⼯具:jsqlparser.jar
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.6</version>
</dependency>
(b) 在MyBatis 的总体⽂件中配置插件
放到之前
<plugins>
<!-- PageHelper4.1.6 -->
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
注意:插件5.1以后interceptor不同,并且不需要指定数据库名字
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
</plugin>
</plugins>
© 在执⾏查询之前设置
PageHelper.startPage(当前⻚,每⻚条数)
//分⻚查询(注意事项:设置分⻚的值⼀定要在查询之前)
//1.在⼯具类中指定⻚码值和显示条数
PageHelper.startPage(2,5);
//2.调取查询的⽅法,得到结果集
Student student1=new Student();
//student1.setStuname(“aa”);
// student1.setAddress1(“昌平”);
List list=dao.findall(student1);
//3.将list集合封装到PageInfo对象中
PageInfo pageInfo=new PageInfo(list);
List list2= pageInfo.getList();
//4.得到结果
for (Student student :list2) {
System.out.println(student.getStuname());
}
System.out.println(“每⻚显示条数:”+pageInfo.getPageSize());
System.out.println(“当前⻚的条数:”+pageInfo.getSize());
System.out.println(“总条数:”+pageInfo.getTotal());
System.out.println(“总⻚数:”+pageInfo.getPages());
System.out.println(“上⼀⻚:”+pageInfo.getPrePage());
System.out.println(“下⼀⻚:”+pageInfo.getNextPage());
System.out.println(“当前⻚:”+pageInfo.getPageNum());
分页测试类
package com;
import com.bean.student;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
public class TestPage {
public static void main(String[] args) {
try {
//1加载配置文件
Reader reader=Resources.getResourceAsReader("mybatis.xml");
/* 2得到SQLSessionFactoryBuilder*/
SqlSessionFactoryBuilder builder =new SqlSessionFactoryBuilder();
SqlSessionFactory build =builder.build(reader);
//3得到SQLSession
SqlSession session=build.openSession();
//4操作sql
//4.1指定分页的参数
PageHelper.startPage(2,3);
//42调取dao层方法
List<student> list = session.selectList("com.dao.studentDao.getall");
//创建分页工具类对象
PageInfo<student> info=new PageInfo<student>(list);
//从分页数据中获得数据
for (student stud : info.getList()) {
System.out.println(stud);
}
System.out.println("每⻚显示条数:"+info.getPageSize());
System.out.println("当前⻚的条数:"+info.getSize());
System.out.println("总条数:"+info.getTotal());
System.out.println("总⻚数:"+info.getPages());
System.out.println("上⼀⻚:"+info.getPrePage());
System.out.println("下⼀⻚:"+info.getNextPage());
System.out.println("当前⻚:"+info.getPageNum());
//5遍历
/* for (student student : list) {
System.out.println(student);
}
*/
session.commit();//做完修改得需要提交事务
//6关闭资源
session.close();
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
mybatis缓存
⼀级缓存
SqlSession 的缓存 ------>⾃动开启
⼆级缓存:
做到从不同的缓存中共享数据
SqlSessionFactory 的缓存 —>需要⼿动开启
映射配置⽂件中配置
<mapper namespace="接⼝路径">
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
</mapper>
说明:
eviction: ⼆级缓存中,缓存的对象从缓存中移除的策略,回收策略为先进先出
flushInterval: 刷新缓存的事件间隔,单位:毫秒
size: 缓存对象的个数
readOnly: 是否是只读的
//不同qlSession,要同⼀个sqlSessionFactory
SqlSessionFactory factory= new SqlSessionFactoryBuilder()
.build(Resources.getResourceAsReader("mybatis-config.xml"));
SqlSession sqlSession1=factory.openSession();
Student student = sqlSession1.selectOne("com.yhp.dao.StudentDao.findbystuid",
1);
System.out.println(student.getSname());
sqlSession1.close();
System.out.println("===================================");
SqlSession sqlSession2= factory.openSession();
student = sqlSession2.selectOne("com.yhp.dao.StudentDao.findbystuid", 1);
System.out.println(student.getSname());
sqlSession2.close();
cache元素⽤来开启当前mapper的namespace下的⼆级缓存,该元素的属性设置如下:
flushInterval:刷新间隔,可以被设置为任意的正整数,⽽且它们代表⼀个合理的毫秒形式的时间段,
默认情况下是不设置的,也就是没有刷新间隔,缓存仅仅调⽤语句时刷新。
//不同qlSession,要同⼀个sqlSessionFactory
SqlSessionFactory factory= new SqlSessionFactoryBuilder()
.build(Resources.getResourceAsReader(“mybatis-config.xml”));
SqlSession sqlSession1=factory.openSession();
Student student = sqlSession1.selectOne(“com.yhp.dao.StudentDao.findbystuid”,
1);
System.out.println(student.getSname());
sqlSession1.close();
System.out.println("===================================");
SqlSession sqlSession2= factory.openSession();
student = sqlSession2.selectOne(“com.yhp.dao.StudentDao.findbystuid”, 1);
System.out.println(student.getSname());
sqlSession2.close();
size:缓存数⽬,可以被设置为任意正整数,要记住你的缓存对象数⽬和你运⾏环境可⽤内存资源数
⽬,默认值是1024.
readOnly:只读,属性可以被设置为true或false,只读的缓存会给所有调⽤者返回缓存对象的相同实
例,因此这些对象不能被修改。这提供了很重要的性能优势,可读写的缓存会返回缓存对象的拷⻉(通
过序列化),这会慢⼀些,但是安全,因此默认是false。
eviction:收回策略,默认为LRU,有如下⼏种:
LRU:最近最少使⽤的策略,移除最⻓时间不被使⽤的对象。
FIFO:先进先出策略,按对象进⼊缓存的顺序来移除它们。
SOFT:软引⽤策略,移除基于垃圾回收器状态和软引⽤规则的对象。
WEAK:弱引⽤策略,更积极地移除基于垃圾收集器状态和弱引⽤规则的对象。
注意:使⽤⼆级缓存时,与查询结果映射的java对象必须实现java.io.Serializable接⼝的序列化和反序列
化操作,如果存在⽗类,其成员都需要实现序列化接⼝,实现序列化接⼝是为了对缓存数据进⾏序列化
和反序列化操作,因为⼆级缓存数据存储介质多种多样,不⼀定在内存,有可能是硬盘或者远程服务
器。
以上源码都在资源mybatis里,如有需要可自行下载
Mybatis 注解
从注解这开始的源码都在资源里Mybatis001里
在mybatis中可以将sql语句通过注解的⽅式定义在java中,此时配置⽂件扫描该注解的位置即可,代码
如下:
@Insert("insert into student(username,password,birthday) values(#
{user_name},#{password},#{birthday})")
@Options(useGeneratedKeys = true,keyProperty = "userid")
public int insertstu(Student student);
@Delete("delete from student where userid=#{userid}")
public int deleteuser(int userid);
@Update("update student set username=#{user_name},sex=#{sex} where userid=#
{userid}")
public int updateuser(Student stu);
@Select("select * from student")
/* @Results({
@Result(id = true, property = "id", column = "test_id")
@Result(column = "username",property = "user_name")
})*/
注意:多个@Result的时候两侧加⼤括号{}
lombok插件
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency
lombok的使⽤
@Data 注解在类上;提供类所有属性的 getting 和 setting ⽅法,此外还提供了equals、canEqual、
hashCode、toString ⽅法
@Setter :注解在属性上;为属性提供 setting ⽅法
@Getter :注解在属性上;为属性提供 getting ⽅法
@Log4j :注解在类上;为类提供⼀个 属性名为log 的 log4j ⽇志对象
@NoArgsConstructor :注解在类上;为类提供⼀个⽆参的构造⽅法
@AllArgsConstructor :注解在类上;为类提供⼀个全参的构造⽅法
@Cleanup : 可以关闭流
@Builder : 被注解的类加个构造者模式
@Synchronized : 加个同步锁
@SneakyThrows : 等同于try/catch 捕获异常
@NonNull : 如果给参数加个这个注解 参数为null会抛出空指针异常
@Value : 注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会⽣
成set⽅法。
@ToString 重写toString()⽅法
mybatis 自动化
源码在mybatis003里
作⽤:反向⽣成实体类,接⼝,mapper.xml
添加依赖包
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>
加载插件
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<configuration>
<!--配置⽂件的路径-->
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
</configuration>
<dependencies>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
修改配置文件
里面的一些配置信息需要修改成自己本地的
<?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>
<!--数据库驱动jar -->
<classPathEntry
location="F:\yhp\jar\mysql驱动\mysql-connector-java-5.0.8-bin.jar"
/>
<context id="MyBatis" targetRuntime="MyBatis3">
<!--去除注释 -->
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/chaoshi"
userId="root"
password="123456">
</jdbcConnection>
<!--⽣成实体类 指定包名 以及⽣成的地址 (可以⾃定义地址,但是路径不存在不会⾃动创建
使⽤Maven⽣成在target⽬录下,会⾃动创建) -->
<javaModelGenerator targetPackage="com.yhp.bean"
targetProject="F:\yhp\three\workspace\mybatis_001\src\main\java">
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!--⽣成SQLmapper⽂件 -->
<sqlMapGenerator targetPackage="mapper"
targetProject="F:\yhp\three\workspace\mybatis_001\src\main\resources">
</sqlMapGenerator>
<!--⽣成Dao⽂件,⽣成接⼝ -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.yhp.dao"
targetProject="F:\yhp\three\workspace\mybatis_001\src\main\java">
</javaClientGenerator>
<table tableName="student" enableCountByExample="false"
enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false">
</table>
<table tableName="grade" enableCountByExample="false"
enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false">
</table>
<table tableName="subject" enableCountByExample="false"
enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false">
</table>
</context>
</generatorConfiguration>
数据库驱动包在本地的maven仓库里
可以看到自动生成了