Mybatis的使用教程在茫茫人海中,相遇既是一种缘分,相知则是一种传递,相遇相知构成了这份友谊,所以希望能够有很多跟我一样可能并非天赋异鼎,但是却对技术充满热爱的人。能够从我的文章中收获到东西。
- 前言
- mybatis是什么?
- mybatis的具体使用流程
- 殺 pom依赖
- mybatis的主配置文件
- 珞 存储jdbc连接信息的文件
- 实体类Student
- 朗 正常的测试流程
- 接口对应的xml文件
- 代理对象的使用
- mybatis中的Param使用
- mybatis中的resultType和resultMap的使用
- 模糊查询的注意点
- 濾 动态sql
- 分页查询
前言
本次的整个mybatis我希望使用引导式的方式来记录自己在学习mybatis过程中是如何一步步理解并掌握的。
提示:以下是本篇文章正文内容,下面案例可供参考
mybatis是什么?学习任何框架之前我都会有一个疑问:这个框架是什么?他有什么作用?以及我应该去学习他的那些内容来完美的掌握这个框架。mybatis也不例外。但是在学习mybatis之前我们要先掌握一个概念:什么是框架?
框架(framework)是一个框子——指其约束性,也是一个架子——指其支撑性。是一个基本概念上的结构,用于去解决或者处理复杂的问题。
框架这个广泛的定义使用的十分流行,尤其在软件概念。框架也能用于机械结构。(来自于百度百科)
我们不如通俗一点来说框架你就当成一个舞台,舞台提供的基础功能每个人都能使用,这个基础功能就相当于其他大佬已经给你写好的类或者功能。你直接拿过来使用即可。
对于框架来说一般一个框架针对于一个特定的领域有效,比如mybatis做数据库操作强,但是不能做其他的。那么我们使用mybatis用来做什么呢?
说白了,就是两件事:
1.Sql映射:
可以把数据库表中的一行数据,映射成为一个java对象
一行数据可以看做是一个java对象,操作这个对象,就相当于操作表中的数据
2.数据访问,对数据库执行增删改查。
也就是mybatis帮我们做了以前我们自己做的事:创建连接对象,关闭资源等。我们现在只需要提供给mybatis一个语句剩下的我们都不需要管了。
mybatis的具体使用流程
基础的文件结构:
殺 pom依赖代码如下:
mybatis的主配置文件org.mybatis mybatis 3.5.5 mysql mysql-connector-java 5.1.47 junit junit 4.12 test
代码如下:
珞 存储jdbc连接信息的文件
代码如下:
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/数据库名称 user=root passwd=自己的数据库密码 实体类Student
代码如下:
package com.bjpowernode.domain;
public class Student {
private Integer id;
private String name;
private String email;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + ''' +
", email='" + email + ''' +
", age=" + age +
'}';
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
朗 正常的测试流程
代码如下:
package com.bjpowernode;
import com.bjpowernode.domain.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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestMyBatis {
@Test
public void test() throws IOException {
// 1.定义mybatis主配置文件的名称,从类路径的根开始(target/classes)
// 也就是编译完成以后 里面找mybatis路径
String config="mybatis.xml";
// 2.读取这个config表示的文件
InputStream in = Resources.getResourceAsStream(config);
// 3.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 4.创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
// 5.【重要】 获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession =factory.openSession();
// 6.【重要】 指定要执行的sql语句的标识,sql映射文件中的 namespace+"."+标签的id值
String sqlId="com.bjpowernode.dao.StudentDao"+"."+"insert";
// 7.执行sql语句,通过sqlId找到语句
Student student=new Student();
student.setId(1004);
student.setName("曹操");
student.setEmail("caocao@qq.com");
student.setAge(26);
int num=sqlSession.insert(sqlId, student);
// 8.输出结果
sqlSession.commit();
// 因为开启了事务所以必须要加上commit,否则只是保存在了缓存里。
// mybatis默认不是自动提交事务
System.out.println("执行的结果"+num);
// 9.关闭sqlSession
sqlSession.close();
}
}
这里由于 每一次测试都会有大量重复的代码所以我们可以把重复代码封装起来方便后续的使用!
代码如下:
package com.bjpowernode.ustils;
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.InputStream;
public class MyBatisUtils {
private static SqlSessionFactory factory=null;
static {
String config ="mybatis.xml";
InputStream in = null;
try {
in = Resources.getResourceAsStream(config);
factory=new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
// 获取SqlSession对象
public static SqlSession getSession()
{ SqlSession sqlSession=null;
if (factory!=null)
{
sqlSession=factory.openSession();//自动提交事务
}
return sqlSession;
}
}
接口对应的xml文件
代码如下:
代理对象的使用select * from student order by id; insert into student values(#{id},#{name},#{email},#{age})
public void test()
{
// 使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口)
// getMapper 能获取dao接口对应的实现类
SqlSession sqlSession= MyBatisUtils.getSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
// 调用dao方法执行操作
Listlist= dao.list();
// com.sun.proxy.&Proxy2:jdk的动态代理
list.forEach(student -> System.out.println(student));
sqlSession.close();
}
截止到上面的正常测试为止我们都没有使用到接口就可以正常的访问我们的xml文件。那么我们的接口文件到底用来干什么呢?对于正常测试里面的代码来说还是过多,显得有点冗余复杂,那么我们如何减少代码量呢?通过代理对象的使用。
对比我们正常测试的代码我们进行分析:
List list =dao.list();
杻 dao对象,类型是StudentDao,全限定名称是com.bjpowernode.dao.StudentDao
全限定名称和namespace是一样的。(这个namespace你可以自定义名称 叫什么都可以,但是我们会让他和接口全限定名称一样,就是为了使用代理对象)
方法名称,list ,这个方法就是mapper文件中的id值list(跟namespace的道理一样)
說 通过dao中方法的返回值也可以确定mybatis 要调用的SqlSession的方法。
如果返回值是List,调用的就是SqlSession.list()方法。 如果返回值是int,或是非List的,看mapper文件中的 标签是就会调用SqlSession的insert,update等方法。
丹mybatis的动态代理:mybatis根据dao的方法调用,获取执行sql语句的信息
mybatis根据你的dao接口,创建出一个dao接口的实现类,并创建这个类的对象
完成SqlSession调用方法,访问数据库。(也就是有了代理对象,mybatis帮你把
原先你需要写的代码通过框架给你实现了。你需要执行的操作变少了。)
那么实现代理对象的操作是什么?
答:
SqlSession sqlSession=MyBatisUtils.getSession(); StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
就是通过getMapper方法获取到StudentDao的类文件。java会通过反射机制帮你获取到接口的代理对象。这样你往后的操作只需要 通过接口调用方法即可实现对于数据库的操作。
这里讲完了正常的mybatis使用流程。我们接下来就讲一下param的使用!
mybatis中的Param使用关于Param的使用:
一个简单类型的传值 : 我们只需要在xml文件中通过#{任意字符}即可获取到传过来的参数。
寧多个参数的传值:
1.使用@Param命名参数
接口 public List selectlist(@Param(“myname”) String name,@Param(“myage”) Integer age )
使用 @Param(“参数名”) String name
mapper 文件:
select * from student where name=#{myname} or age=#{myage}
2.使用对象传值
将你的对象里面的属性赋值后,他就类似于一个键值对的形式,id=1,name=“李四” 所以你要获取到对象的值。直接通过#{id} , #{name}即可获取。
3.按位置传值(不重要)
mybatis 3.4之前,使用 #{0},#{1}
mybatis 3.4之后,使用#{arg0},#{arg1}
4.通过Map传值(不重要,这个就类似于你的对象传值)
就是map.put(“myname”,“李四”) 通过接口参数传递。
然后xml文件通过#{myname}获取值。
下面是相关代码:
xml文件:
select * from student where id = ${id} ; -- 这个可以是任意的字符 不非得是 id!!!!
测试文件:
@Test
public void test()
{
SqlSession sqlSession = MyBatisUtils.getSession();
StudentDao studentDao= sqlSession.getMapper(StudentDao.class);
Student student=studentDao.list(1007);
System.out.println(student);
sqlSession.close();
}
@Test
public void test1(){
SqlSession sqlSession=MyBatisUtils.getSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
// Listlist=studentDao.selectlist("李四", 28);
QueryParam queryParam=new QueryParam();
queryParam.setParamage(28);
queryParam.setParamname("zhangsan");
List list=studentDao.paramlist(queryParam);
list.forEach(student -> System.out.println(student));
sqlSession.close();
// 这里直接用哪个Student对象就行。 然后里面就传两个值就好了。
// 到时候就接受这俩值
}
@Test
public void test2(){
SqlSession sqlSession=MyBatisUtils.getSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
Map map=new HashMap<>();
map.put("myname", "张三");
map.put("myage",20);
List list=studentDao.selectMap(map);
list.forEach(student -> System.out.println(student));
sqlSession.close();
}
@Test
public void test3(){
SqlSession sqlSession=MyBatisUtils.getSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
List list=studentDao.selectUse$("age");
list.forEach(student -> System.out.println(student));
sqlSession.close();
}
索讲完param的传值 接下来就是resultType,顾名思义:resultType就是结果集的意思,那么对于结果集来说跟谁的联系最大?select语句!!
mybatis中的resultType和resultMap的使用根据上面的提示:select语句跟resultType是息息相关的。那么原因是什么?在我们jdbc的学习阶段我们知道最后通过预编译提交 ps.executeQuery() (这个ps是预编译的对象) 后我们会获得一个 结果集。 然后 rs. next() 我们会将数据库中的每一条数据通过一个对象存储起来并且返回!!! 这个对象类型就是我们resultType的类型。
也就是说我们通过规定 resultType类型的值来决定那个对象去获取到数据库的数据。 这也就跟开始说的mybatis框架作用对照:
可以把数据库表中的一行数据,映射成为一个java对象 一行数据可以看做是一个java对象,操作这个对象,就相当于操作表中的数据
1. 对象映射
通过设置 resultType的值是对象类型(全限定名称)来 映射数据库中的一行数据 ,也就是将这一行数据存放在你定义的这个类型的对象中。 注意:字段名必须和属性名一一对应 所以这也就是为什么我们要根据数据库的表建立对应实体类的目的。
2.Map映射
我们既然知道 对象是属性=value 的形式 那么这跟map 的键值对很相似。所以我们也可以设置
也就是map的键就是你的数据库中表的字段名 值就是数据库中的值。然后会以map对象返回。
3.resultMap的使用
select * from student
resultMap就是为了解决你的对象跟字段名不一样的问题。因为需要相同才可以一一映射。如果不一样我们就无法获取数据库的数据。所以通过resultMap
可以指定字段名跟对象的那个属性进行映射。
列名和属性名不一样:第二种方式
resultType的默认原则是 同名的列值赋值给同名的属性, 使用列别名。
模糊查询的注意点select id as myid,name as myname ,email as myemail,age as myage from student
这里有两种方式来做模糊查询
- 正常的 使用#{}去接受数据,只需要你在测试的时候加入 "李%"即可
public void test5(){
SqlSession sqlSession=MyBatisUtils.getSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
String name ="李%";
List alist=studentDao.selectLikeOne(name);
alist.forEach(myStudent -> System.out.println(myStudent));
sqlSession.close();
}
select id,name,email,age from student where name like #{name}
- 藍第二种方式就是拼接你可以通过concat或者直接拼接都可以
select id,name,email,age from student where name like "%" #{name} "%"
concat拼接
concat('%', #{name},'%')
濾 动态sql
✨首先是if的使用:
1.if 是判断条件的语法:
如果我们单纯的使用if语句会出现问题。因为你的sql语句需要进行拼接。当你使用if 语句的时候。拼接不是一个完整的sql语句他就会显示语法错误。
例如:
select * from student where 1=1 and name=#{name} or age=#{age}
从这一段代码中我们可以看到如果不加 where 1=1的这个条件时,当第一个条件符合,那么拼接and 就会变成
select * from student and name=#{name}
很明显这个语法是错误的。并且你即使加了 where 1=1 这个条件在和 包含or的语句拼接时也是错误的。
2.所以为了避免这个错误我们的where就要跟if标签一起使用:
select * from student name=#{name} or age>#{age}
where标签的作用就是自动给你添加where条件并自动给你删除or或者多余的and。避免了你手动拼接的错误!
3.foreach标签的用法:
接口文件:
ListselectForeachTwo(List list);
xml文件:
select * from student where id in #{stuid.id}
首先collection: 这个属性的意思是接口传进来的参数类型。如果是数组使用array,如果是list集合使用list
item:你自定义的名字,表示你传进来的list或者数组的其中一个对象。
open:循环开始的字符
close:循环结束的字符
separator:集合成员之间的分隔符
这里再引入一个概念 sql代码片段:
我们直接将某个经常使用的代码放入代码片中。
藍1.先使用
select id,name,age,email from student
2.再使用
分页查询where id in #{myid}
邏 对于分页查询如果我们使用前端ajax传数据然后后端使用 limit #{page},#{pagesize} 的方法获取分页数据很麻烦。所以通过pageHelper我们就不需要去写limit语句。
1.首先我们要导入pageHelper的依赖:
最新版:可以去maven官网找
com.github.pagehelper pagehelper 5.1.10
2.接口的方法:
// 使用pageHelper分页数据
List selectAll();
3.xml文件:
select * from student order by id
4.测试类(我们在测试类中使用pageHelper):
@Test
public void testpagehelper()
{
SqlSession sqlSession=MyBatisUtils.getSession();
StudentDao studentDao= sqlSession.getMapper(StudentDao.class);
// 加入PageHelper的方法,分页
pageNum:第几页,从1开始
pageSize:一页中有多少行数据
PageHelper.startPage(2, 3);
List list1= studentDao.selectAll();
list1.forEach(student -> System.out.println(student));
sqlSession.close();
}



