Mybatis框架的使用步骤
前期准备1. 创建Maven工程2. 加入相关的依赖3. 创建实体类,保存表中一行的数据4. 创建持久层的dao接口5. 创建mapper配置文件6.创建主配置文件和数据库信息配置文件
创建数据库信息配置文件:创建主配置文件: 7. 创建获取SqlSession对象的工具类8. 通过mybatis的动态代理获取dao对象 MyBatis 使用传统 Dao 开发方式
(1) 创建 Dao 接口实现类(2)实现接口中 select 方法(3)实现接口中 insert 方法(4)实现接口中 update 方法(5)实现接口中 delete 方法使用方法 传统 Dao 开发方式的分析 动态sql
动态 SQL 之 < if >动态 SQL 之< where >动态 SQL 之 < foreach >
(1) 遍历 List<简单类型>(2) 遍历 List<对象类型> 动态 SQL 之代码片段动态sql总结 主配置文件说明
包含mapper文件的两种方式自动提交事务 pageHelper数据分页
实现步骤:
(1) maven 坐标(2) 加入 plugin 配置(3) PageHelper 对象 其他零碎知识
mybatis框架是对JDBC的一个封装
jdbc的缺点
代码比较多,开发效率低需要关注 Connection ,Statement, ResultSet 对象创建和销毁对 ResultSet 查询的结果,需要自己封装为 List重复的代码比较多些业务代码和数据库的操作混在一起
MyBatis 解决的主要问题
减轻使用 JDBC 的复杂性,不用编写重复的创建 Connetion , Statement ; 不用编写关闭资源代码。
直接使用 java 对象,表示结果数据。让开发者专注 SQL 的处理。 其他分心的工作由 MyBatis 代劳。
mybatis框架是对表实现增删查改操作,不会创建表,所以需要先创建出一个表
CREATE TABLE `student` ( `id` int(11) NOT NULL , `name` varchar(255) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
mysql的简单操作参考
1. 创建Maven工程
创建Maven工程选择archetype创建,选择图中的组件,next
输入包名和文件名,next
finish创建完成
加入mybatis依赖和JDBC依赖和单元测试依赖
junit junit 4.11 test org.mybatis mybatis 3.5.1 mysql mysql-connector-java 8.0.28
在build标签中加入
src/main/java ***.xml false
用于构建文件结构
完整的配置文件如下:
4.0.0 com.changsha Mybatis 1.0-SNAPSHOT UTF-8 1.8 1.8 junit junit 4.11 test org.mybatis mybatis 3.5.1 mysql mysql-connector-java 8.0.24 src/main/java ***.xml false
创建文件结构如下
package com.changsha.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;
}
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;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + ''' +
", email='" + email + ''' +
", age=" + age +
'}';
}
}
4. 创建持久层的dao接口
package com.changsha.dao;
import com.changsha.domain.Student;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
public interface StudentDao {
public List selectStudent();
public Integer insertStudent(Student student);
public Integer deleteStudent(@Param("argID") Integer id,@Param("argName") String name);
public Integer updateStudent(Map args);
}
5. 创建mapper配置文件
mapper文件的名称要和dao接口的名字一样 要和对应的dao接口放在同一个目录下
namespace的值是dao接口的全限定名称
id 是dao方法的名字
内容如下:
6.创建主配置文件和数据库信息配置文件mapper文件主要是保存了sql语句
主配置文件主要是数据库信息,和一些mapper文件的位置信息。
项目 src/main 下创建 resources 目录,设置 resources 目录为 resources root
在resources目录下创建jdbc.properties文件, key: 一般使用 . 做多级目录的。
内容如下:
jdbc.driver = com.mysql.cj.jdbc.Driver jdbc.url = jdbc:mysql://localhost:3306/study jdbc.username = root jdbc.password = 123456创建主配置文件:
创建主配置文件:名称为 mybatis.xml
说明:主配置文件名称是自定义的,内容如下:
其中打印日志的设置为
7. 创建获取SqlSession对象的工具类
这个类主要是为了快速获取SqlSession的对象,减少代码冗余。
public class StudentUtil {
private static SqlSessionFactory factory = null;
static {
String config = "mybatis.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(config);
factory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession的方法
public static SqlSession getSqlSession(){
SqlSession sqlSession = null;
if (factory != null){
sqlSession = factory.openSession();
}
return sqlSession;
}
}
8. 通过mybatis的动态代理获取dao对象
package com.changsha;
import com.changsha.dao.StudentDao;
import com.changsha.domain.Student;
import com.changsha.util.StudentUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class test {
@Test
public void myTest(){
//1. 通过工具类获取SqlSession对象
SqlSession session = StudentUtil.getSqlSession();
//2.通过mybatis框架的动态代理获取mybatis实现的对象
StudentDao studentDao = session.getMapper(StudentDao.class);
//3. 功能
//1).增加(对象传递参数)
Student student = new Student();
student.setId(100);
student.setName("王五");
student.setEmail("wangwu@");
student.setAge(111);
studentDao.insertStudent(student);//调用动态代理生成的对象
session.commit();//提交事务
// 2)查找
List studentList;
studentList = studentDao.selectStudent();
studentList.forEach( stu -> System.out.println(stu));
// //3)删除(注解Param传递参数)
studentDao.deleteStudent(100,"王五");
session.commit();
//4) 更新(Map传递多参数)
Map map = new HashMap<>();
map.put("oldArg",10);
map.put("newArg",13);
studentDao.updateStudent(map);
session.commit();
// 2)查找
studentList = studentDao.selectStudent();
studentList.forEach( stu -> System.out.println(stu));
//4.关闭 SqlSession,释放资源
session.close();
}
}
MyBatis 使用传统 Dao 开发方式
以上方法是调用getMapper方法获取MyBatis框架中动态代理生成的对象。传统的方法
(1) 创建 Dao 接口实现类执行sql语句需要定位到mapper文件中对应语句的id。
namespace.id的方式需要到sql语句
public class StudentDaoImpl implements StudentDao(2)实现接口中 select 方法
public ListselectStudent() { SqlSession session = MyBatisUtil.getSqlSession(); List studentList = session.selectList( "com.changsha.dao.StudentDao.selectStudent"); session.close(); return studentList; }
测试查询操作
MyBatisTest 类中创建 StudentDaoImpl 对象
public class MyBatisTest {
StudentDao studentDao = new StudentDaoImpl();
@Test
public void testSelect() throws IOException {
final List studentList = studentDao.selectStudents();
studentList.forEach( stu -> System.out.println(stu));
}
}
(3)实现接口中 insert 方法
public int insertStudent(Student student) {
SqlSession session = MyBatisUtil.getSqlSession();
int nums = session.insert(
"com.changsha.dao.StudentDao.insertStudent",student);
session.commit();
session.close();
return nums;
}
测试 insert
@Test
public void testInsert() throws IOException {
Student student = new Student();
student.setId(1006);
student.setName("林浩");
student.setEmail("linhao@163.com");
student.setAge(26);
int nums = studentDao.insertStudent(student);
System.out.println("使用 Dao 添加数据:"+nums);
}
(4)实现接口中 update 方法
public int updateStudent(Student student) {
SqlSession session = MyBatisUtil.getSqlSession();
int nums = session.insert(
"com.changsha.dao.StudentDao.updateStudent",student);
session.commit();
session.close();
return nums;
}
测试 update
@Test
public void testUpdate() throws IOException {
Student student = new Student();
student.setId(1006);
student.setAge(28);
int nums = studentDao.updateStudent(student);
System.out.println("使用 Dao 修改数据:"+nums);
}
(5)实现接口中 delete 方法
public int deleteStudent(int id) {
SqlSession session = MyBatisUtil.getSqlSession();
int nums = session.insert(
"com.bjpowernode.dao.StudentDao.deleteStudent",1006);
session.commit();
session.close();
return nums;
}
测试 delete
@Test
public void testDelete() throws IOException {
int nums = studentDao.deleteStudent(1006);
System.out.println("使用 Dao 修改数据:"+nums);
}
使用方法
直接使用接口的实现类就行
传统 Dao 开发方式的分析动态sql在前面例子中自定义 Dao 接口实现类时发现一个问题:Dao 的实现类其实并没有干什么实质性的工作,它仅仅就是通过 SqlSession 的相关 API 定位到映射文件 mapper 中相应 id 的 SQL 语句,真正对 DB 进行操作的工作其实是由框架通过 mapper 中的 SQL 完成的。所以,MyBatis 框架就抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,对DB 进行操作。这种对 Dao 的实现方式称为 Mapper 的动态代理方式。Mapper 动态代理方式无需程序员实现 Dao 接口。接口是由 MyBatis 结合映射文件自动生成的动态代
理实现的。
相当于使用判断,循环等方式拼接出需要的SQL语句
动态 SQL 之 < if >动态 SQL,通过 MyBatis 提供的各种标签对条件作出判断以实现动态拼接 SQL 语句。这里的条件判
断使用的表达式为 OGNL 表达式。常用的动态 SQL 标签有、 、 、 等。
MyBatis 的动态 SQL 语句,与 JSTL 中的语句非常相似。
动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行
查询。提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一列出,对所有条件进行
排列组合,将会出现大量的 SQL 语句。此时,可使用动态 SQL 来解决这样的问题
对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中。
语法:sql 语句的部分
接口方法
public ListselectIf(@Param("name") String myName,@Param("age") Integer myAge);
这里参数的使用和前面是一样的
mapper文件
测试
@Test
public void myTest(){
//1. 通过工具类获取SqlSession对象
SqlSession session = StudentUtil.getSqlSession();
//2.通过mybatis框架的动态代理获取mybatis实现的对象
StudentDao studentDao = session.getMapper(StudentDao.class);
//3. 功能
List students = new ArrayList<>();
students = studentDao.selectIf("章",111);
students.forEach(stu -> System.out.println(stu));
//4.关闭 SqlSession,释放资源
session.close();
}
动态 SQL 之< where >
标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若 where 后的所有 条件均为 false,而 where 后若又没有 1=1 子句,则 SQL 中就会只剩下一个空的 where,SQL出错。所以,在 where 后,需要添加永为真子句 1=1,以防止这种情况的发生。但当数据量很大时,会严重影响查询效率。
使用标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加where 子句。需要注意的是,第一个 标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错,系统会将多出的 and 去掉。但其它中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错。
语法:其他动态 sql
接口方法
public ListselectIf(@Param("name") String myName,@Param("age") Integer myAge);
mapper文件
测试
@Test
public void myTest(){
//1. 通过工具类获取SqlSession对象
SqlSession session = StudentUtil.getSqlSession();
//2.通过mybatis框架的动态代理获取mybatis实现的对象
StudentDao studentDao = session.getMapper(StudentDao.class);
//3. 功能
List students = new ArrayList<>();
students = studentDao.selectIf("章",1);
students.forEach(stu -> System.out.println(stu));
//4.关闭 SqlSession,释放资源
session.close();
}
动态 SQL 之 < foreach >
标签用于实现对于数组与集合的遍历。对其使用,需要注意:
➢ collection 表示要遍历的集合类型, list ,array 等。
➢ open、close、separator 为对遍历内容的 SQL 拼接。
语法:
(1) 遍历 List<简单类型>#{item 的值}
表达式中的 List 使用 list 表示,其大小使用 list.size 表示。
需求:查询学生 id 是 1002,1005,1006
接口方法:
ListselectStudentForList(List idList)
mapper文件
测试方法:
@Test
public void testSelectForList() {
List list = new ArrayList<>();
list.add(1002);
list.add(1005);
list.add(1006);
List studentList = studentDao.selectStudentForList(list);
studentList.forEach( stu -> System.out.println(stu));
}
(2) 遍历 List<对象类型>
接口方法:
ListselectStudentForList2(List stuList);
mapper 文件:
测试方法:
@Test
public void testSelectForList2() {
List list = new ArrayList<>();
Student s1 = new Student();
s1.setId(1002);
list.add(s1);
s1 = new Student();
s1.setId(1005);
list.add(s1);
List studentList = studentDao.selectStudentForList2(list);
studentList.forEach( stu -> System.out.println(stu));
}
动态 SQL 之代码片段
标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用
子标签。该 标签可以定义 SQL 语句中的任何部分,所以 子标签可以放在动态 SQL
的任何位置。
接口方法:
ListselectStudentSqlFragment(List stuList);
mapper 文件:
select id,name,email,age from student where id in #{stuobject.id}
测试方法:
@Test
public void testSelectSqlFragment() {
List list = new ArrayList<>();
Student s1 = new Student();
s1.setId(1002);
list.add(s1);
s1 = new Student();
s1.setId(1005);
list.add(s1);
List studentList = studentDao.selectStudentSqlFragment(list);
studentList.forEach( stu -> System.out.println(stu));
}
动态sql总结
主配置文件说明
包含mapper文件的两种方式
第一种方式:指定多个mapper文件
第二种方式: 使用包名
name参数为xml文件(mapper文件)所在的包名, 这个包中所有xml文件一次都能加载给mybatis
使用package的要求:
1. mapper文件名称需要和接口名称一样, 区分大小写的一样
2. mapper文件和dao接口需要在同一目录
自动提交事务
自动提交事务
设置自动提交的方式,factory 的 openSession() 分为有参数和无参数的。
有参数为 true,使用自动提交,可以修改 MyBatisUtil 的 getSqlSession()方法。
session = factory.openSession(true);
再执行 insert 操作,无需执行 session.commit(),事务是自动提交的
Mybatis 通用分页插件
实现步骤: (1) maven 坐标(2) 加入 plugin 配置com.github.pagehelper pagehelper 5.1.10
在主配置文件
(3) PageHelper 对象
查询语句之前调用 PageHelper.startPage 静态方法。
除了 PageHelper.startPage 方法外,还提供了类似用法的 PageHelper.offsetPage 方法。
在你需要进行分页的 MyBatis 查询方法前调用 PageHelper.startPage 静态方法即可,紧跟在这个
方法后的第一个 MyBatis 查询方法会被进行分页。
@Test
public void myTest(){
//1. 通过工具类获取SqlSession对象
SqlSession session = StudentUtil.getSqlSession();
//2.通过mybatis框架的动态代理获取mybatis实现的对象
StudentDao studentDao = session.getMapper(StudentDao.class);
//3. 功能
//pageNum参数表示第几页,PageSize表示每页有几条数据
PageHelper.startPage(1,2);
List students = new ArrayList<>();
students = studentDao.selectPage();
students.forEach(stu -> System.out.println(stu));
//4.关闭 SqlSession,释放资源
session.close();
}
startPage函数中,第一个参数pageNum参数表示第几页,第二个PageSize表示每页有几条数据
其他零碎知识在mapper文件中能用#{}的地方都能用${}
5) # 和 $
select id,name, email,age from student where id=#{studentId}
# 的结果: select id,name, email,age from student where id=?
select id,name, email,age from student where id=${studentId}
$ 的结果:select id,name, email,age from student where id=1001
String sql="select id,name, email,age from student where id=" + "1001";
使用的Statement对象执行sql, 效率比PreparedStatement低。
$:可以替换表名或者列名, 你能确定数据是安全的。可以使用$
# 和 $区别
1. #使用 ?在sql语句中做站位的, 使用PreparedStatement执行sql,效率高
2. #能够避免sql注入,更安全。
3. $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
4. $有sql注入的风险,缺乏安全性。
5. $:可以替换表名或者列名



