Mybatis
1.框架概述
1.1 软件开发常用结构
1.1.1 三层架构
1.三层架构包含的三层:
界面层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)
三层的职责:
- 界面层(表示层,视图层):主要功能是接受用户的数据,显示请求的处理结果。使用web页面和
用户交互,手机app也就是表示层的,用户在app中操作,业务逻辑在服务器端处理。 - 业务逻辑层:接收表示传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取数据。
- 数据访问层:与数据库打交道。主要实现对数据的增、删、改、查。将存储在数据库中的数据提交
给业务层,同时将业务层处理的数据保存到数据库.
三层的处理请求的交互:
用户-->界面层-->业务逻辑层-->数据访问层-->DB数据库
界面层:
? 和用户打交道的,接收用户的请求参数,显示处理结果的 。(jsp ,html ,servlet)
业务逻辑层:
? 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据
数据访问层:
? 就是访问数据库,执行对数据的查询,修改,删除等等的。
三层对应的包
界面层: controller包( servlet)
业务逻辑层: service 包(xxXService类 )
数据访问层:dao包( XXXDao类)
三层中类的交互
用户使用界面层-->业务逻辑层--->数据访问层(持久层) -->数据库(mysql)
三层对应的处理框架
界面层---servlet--- springmvc ( 框架)
业务逻辑层---service类--spring (框架)
数据访问层---dao类--mybatis (框架)
2.框架
框架是-一个舞台,一个模版
模版:
1.规定了好一些条款,内容。
2.加入自己的东西
框架是一一个模块
1.框架中定义好了--些功能。这些功能是可用的。
2.可以加入项目中自己的功能,这些功能可以利用框架中写好的功能。
框架是-一个软件,半成品的软件,定义好了一些基础功能,需要加入你的功能就是完整的。
基础功能是可重复使用的,可升级的。
框架特点:
1.框架一般不是全能的,不能做所有事情
2.框架是针对某一个领域有效。特长在某一-个方面,比如mybatis做数据库操作强,但是他不能做其它的。
3.框架是一一个软件
1.2 Mybatis框架概述
mybatis框架
? 一个框架,早期叫做ibatis,代码在github.
? mybatis是MyBatis SQL Mapper Framework for Java (sql映射框架)
? 1)sql mapper:sql映射
? 可以把数据库表中的一行数据映射为一个java对象。
? 一行数据可以看做是-一个java对象。操作这个对象,就相当于操作表中的数据
? 2) Data Access Objects (DAOs) :数据访问,对数据库执行增删改查。
mybatis提供了哪些功能:
1.提供了创建Connection, statement, Resultset的能力,不用开发人员创建这些对象了
2.提供了执行sql语句的能力,不用你执行sql
? 3.提供了循环sql, 把sql的结果转为java对象, List集合的能力
while (rs .next()) {
Student stu = new
student() ;
stu.setId(rs.getInt("id"));
stu.setName(rs.getstring("name")) ;
stu.setAge(rs.getInt("age")) ;
//从数据库取出数据转为Student 对象,封装到List 集合
stuList.add(stu) ;
}
? 4.提供了关闭资源的能力,不用你关闭Conneqtion, statement, Resultset
开发人员做的是: 提供sql语句
最后是: 开发 人员提供sql语句--mybatis处理sq1---开发人员得到List集合或java对象(表中的数据)
总结:
mybatis是一一个sql映射框架,提供的数据库的操作能力。增强的JDBC,
使用mybatis让开发人员集中精神写sq1就可以了,不必关心Connection, statement , Resultset
的创建,销毁,sql 的执行。
2.Mybatis使用步骤
2.1 实现步骤(执行select语句)
1.新建一个student表
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)
)
2.在maven中加入mybatis和mysql驱动和junit的依赖坐标
org.mybatis
mybatis
3.5.1
mysql
mysql-connector-java
5.1.9
junit
junit
4.11
test
src/main/resources
**/*.properties
**/*.xml
true
src/main/java
**/*.properties
**/*.xml
true
3.创建实体类,Student--保存表中的一行数据
创建包com.cjj.pojo,在pojo包下创建Student实体类
package com.cjj.pojo;
public class Student {
private int id;
private String name;
private String email;
private Integer age;
public Student() {
}
public Student(int id, String name, String email, Integer age) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int 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接口,定义操作数据库的方法
创建包com.cjj.dao,在dao包下创建StudentDao接口.
package com.cjj.dao;
import com.cjj.pojo.Student;
import java.util.List;
public interface StudentDao {
//查询Student表的所有数据
public List selectStudents();
}
5.创建一个mybatis使用的配置文件:
<?xml version="1.0" encoding="UTF-8" ?>
? 叫做sql映射文件:写sql语句的。一般一个表一个sql映射文件。
6.创建mybatis的主配置文件:
? 一个项目就一个主配置文件。
? 主配置文件提供了数据库的连接信息和sql映射文件的位置信息
<?xml version="1.0" encoding="UTF-8" ?>
7.创建使用mybatis类:
? 通过mybatis访问数据库。
创建测试类,测试查询所有学生信息
package com.cjj;
import com.cjj.pojo.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.InputStream;
import java.util.List;
public class MyTest {
@Test
public void selectStudents() throws IOException {
//获取mybatis配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory对象
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
//获取SqlSession对象
SqlSession sqlSession = build.openSession();
//执行sql语句
List studentList = sqlSession.selectList("com.cjj.dao.StudentDao.selectStudents");
for (Student student : studentList) {
System.out.println(student);
}
sqlSession.close();
}
}
查询结果
2.2 mybatis 执行insert语句
1.在dao接口中增加方法
public int insertStudent(Student student);
2.在对应的xml文件中编写sql语句
insert into mybatis.student(id, name, email, age) VALUES (${id},${name},${email},${age});
3.在测试类中执行
@Test
public void insertStudent() throws IOException {
//获取mybatis配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory对象
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
//获取SqlSession对象
SqlSession sqlSession = build.openSession();
//创建一个学生对象
Student student = new Student(3,"王五","wangwu@qq.com",20);
//执行sql语句
int insert = sqlSession.insert("com.cjj.dao.StudentDao.insertStudent", student);
System.out.println(insert);
sqlSession.commit();
sqlSession.close();
}
2.3 配置日志
在mybatis-config.xml配置文件中开启日志
3. Mybatis详解
3.1 SqlSession等主要类的介绍
-
Resources: mybatis中 的一个类,负责读取主配置文件
Inputstream in = Resources . getResourceAsStream ("mybatis-config .xml") ; -
SqlSessionFactoryBuilder : 创建SqlSessionFactory对象,
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder() ;
//创建SqlSessionFactory对象
SqlSessionFactory sqlSessionfactory = builder .build(in) ; -
sqlsessionFactory :重量级对象,程序 创建-一个对象耗时比较长,使用资源比较多,在整个项目中,有一个就够用了。
SqlSessionFactory:接口, 接口实现类: Defaul tsqlSessionFactory
sqlSessionFactory作用: 获取sqlSession对象。 SqlSession sqlSession = factory . openSession() ;
opensession()方法说明:
-
openSession() :无参数的,获取 是非自动提交事务的sqlSession对象
-
openSession (boolean) : openSession(true) 获取 自动提交事务的sqlSession.
? openSession (false)非 自动提交事务的sqlSession对象
- sqlSession:
sqlsession接口:定义了操作数据的方法例如selectOne () , selectlist() , insert() ,update(), delete(), comnit(), rollback()
SqlSession接口的实现类DefaultSqlSession.
使用要求: SqlSession对象不是线程安全的,需要在方法内部使用,在执行sql 语句之前,使用openSession ()获取sqlsession()
在执行完sql语句后,需要关闭它,执行sqlSession.close() .这样能保证他的使用是线程安全的。
3.2 创建工具类MybatisUtils
1.创建一个包com.cjj.utils,在包下创建MybatisUtils工具类
package com.cjj.utils;
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 sqlSessionFactory = null;
static{
try {
//创建sqlSessionFactory对象
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
//返回一个SqlSession对象
public static SqlSession getSqlSession(){
SqlSession sqlSession = null;
if(sqlSessionFactory != null){
sqlSession = sqlSessionFactory.openSession();
}
return sqlSession;
}
}
2.在测试类中测试
@Test
public void selectStudents() throws IOException {
SqlSession sqlSession = MybatisUtils.getSqlSession();
//执行sql语句
List studentList = sqlSession.selectList("com.cjj.dao.StudentDao.selectStudents");
for (Student student : studentList) {
System.out.println(student);
}
sqlSession.close();
}
3.3 传统dao使用方式
1.创建接口实现类实现Studentdao接口的方法
public class StudentDaoImpl implements StudentDao {
@Override
public List selectStudents() {
//获取sqlSession
SqlSession sqlSession = MybatisUtils.getSqlSession();
//执行StudentDao.xml中的sql语句
List studentList = sqlSession.selectList("com.cjj.dao.StudentDao.selectStudents");
//关闭sqlSession
sqlSession.close();
//返回查询出来的学生信息
return studentList;
}
2.编写测试类
@Test
public void selectStudents(){
//创建dao接口实现类对象
StudentDaoImpl stu = new StudentDaoImpl();
//调用实现类中的方法查询学生信息
List studentList = stu.selectStudents();
for (Student student : studentList) {
System.out.println(student);
}
}
传统dao执行insert语句
1.实现接口方法
@Override
public int insertStudent(Student student) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
int count = sqlSession.insert("com.cjj.dao.StudentDao.insertStudent",student);
sqlSession.commit();
sqlSession.close();
return count;
}
2.在测试类中运行
@Override
public int insertStudent(Student student) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
int count = sqlSession.insert("com.cjj.dao.StudentDao.insertStudent",student);
sqlSession.commit();
sqlSession.close();
return count;
}
3.4 Mybatis动态代理getMapper执行sql语句
//查询
@Test
public void selectStudents(){
//获取sqlSession
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
List studentList = mapper.selectStudents();
for (Student student : studentList) {
System.out.println(student);
}
sqlSession.close();
}
//插入
@Test
public void insertStudent() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
int count = mapper.insertStudent(new Student(7, "沸羊羊", "feiyy@qq.com", 20));
System.out.println(count);
sqlSession.commit();
sqlSession.close();
}
3.5 mybatis多种传参数方式
3.5.1 parameterType使用
2.传入参数: .
从java代码中把数据传入到mapper文件的sql语句中。
- parameterType :写在mapper文件中的一个属性。表示dao接口中方法的参数的数据类型
例如StudentDao接口
public Student selectstudentById (Integer id)
2)一个简单类型的参数:
简单类型:mybatis把java的基本数据类型和string都叫简单类型。
在mapper文件获取简单类型的一个参数的值,使用#{任意字符}
接口: public student selectstudentById (Integer id)
mapper: select id,name, email,age from student where id=# {studentId} :
在接口中定义方法
//根据id查询一个学生
public Student getStudentById(int id);
在mapper文件中编写sql语句
在测试类中运行
@Test
public void getStudentById() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
Student stu = mapper.getStudentById(3);
System.out.println(stu);
sqlSession.commit();
sqlSession.close();
}
3.5.2 @Param的使用(传递多个参数)
1.编写接口方法
//使用@Param
public Student getStudentParam(@Param("name")String name,@Param("age")int age);
2.编写sql
3.在测试类中测试
@Test
public void getStudentParam() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
Student stu = mapper.getStudentParam("喜羊羊",18);
System.out.println(stu);
sqlSession.close();
}
3.5.3 使用对象传参
1.将要传入的参数封装为一个实体类
package com.cjj.pojo;
public class Student02 {
private String myname;
private int myage;
public Student02() {
}
public Student02(String myname, int myage) {
this.myname = myname;
this.myage = myage;
}
public String getMyname() {
return myname;
}
public void setMyname(String myname) {
this.myname = myname;
}
public int getMyage() {
return myage;
}
public void setMyage(int myage) {
this.myage = myage;
}
}
2.在接口中编写方法
//使用对象传参
public Student getStudentByStudent02(Student02 student02);
3.编写sql
4.在测试类中运行
@Test
public void getStudentByStudent02() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
Student stu = mapper.getStudentByStudent02(new Student02("张三",19));
System.out.println(stu);
sqlSession.close();
}
3.5.4 按参数位置传值(最好别用)
1.在接口中编写方法
//按位置传参
public Student getStudentByLocal(String name,int age);
2.编写sql语句
3.在测试类中运行
@Test
public void getStudentByLocal() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
Student stu = mapper.getStudentByLocal("李四",20);
System.out.println(stu);
sqlSession.close();
}
3.5.5 使用Map传参(不建议使用)
1.在接口中编写方法
//使用Map传参
public Student getStudentByMap(Map map);
2.编写sql语句
3.在测试类中运行
@Test
public void getStudentByMap() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
Map map = new HashMap<>();
map.put("name","灰太狼");
map.put("age",21);
Student stu = mapper.getStudentByMap(map);
System.out.println(stu);
sqlSession.close();
}
3.6 sql语句编写,使用#和$的区别
select id, name,email,age from student where id= # { studentId}
使用#的结果: .
select id, name, email ,age from student where id= ?(底层使用的是Preparedstatement)
select id, name, email ,age from student where id=${studentId}
使用$的结果:
select id, name,email,age from student where id= 1001(底层使用的是statement)
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. $有sq1注入的风险,缺乏安全性。
5. $:可以替换表名或者列名
4. Mybatis输出结果
mybatis执行了sql语句,得到java对象
4.1 resultType
结果类型,指sql语句执行完毕后,数据转化为java对象。
- resultType结果类型,指sql 语句执行完毕后,数据转为的java对象,java类型 是任意的。
处理方式:
-
mybatis执行sql语句,然后mybatis调用类的无参数构造方法,创建对象。
-
mybatis把Resultset指定列值付给同名的属性。
对等的jdbc
Resultset rs = executeQuery(" select id, name, email,age from student" )
while (rs.next()) {
student
student = new Student() ;
student. setId (rs. getInt ("id") ) ;
student. setName (rs . getstring ("name") )
}
4.1.1 返回简单类型(int等)
? 1.在接口中编写方法
//返回Student表中的人数
public int getStudentCount();
2.编写sql语句
3.在测试类中运行
@Test
public void getStudentCount(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
int studentCount = mapper.getStudentCount();
System.out.println(studentCount);
sqlSession.close();
}
4.1.2 返回对象类型
1.在接口中编写方法
//根据id查询一个学生
public Student getStudentById(int id);
2.编写sql语句
3.在测试类中运行
@Test
public void getStudentById() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
Student stu = mapper.getStudentById(3);
System.out.println(stu);
sqlSession.commit();
sqlSession.close();
}
4.1.3 返回Map(只能返回一行记录)
1.在接口中编写方法
//返回一个Map
public Map getStudentByMap(@Param("id") int id);
2.编写sql
3.在测试类中运行
@Test
public void getStudentByMap(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
Map map = mapper.getStudentByMap(5);
System.out.println(map);
sqlSession.close();
}
4.2 reaultMap
resultMap:结果映射,指定数据库列名和java对象的属性对应关系。
你自定义列值赋值给哪个属性
? 当你的数据库列名和属性名不一样时,一定使用resultMap
1.在接口中编写方法
//返回所有学生
public List getStudentList();
2.编写sql
3.在测试类中运行
@Test
public void getStudentList(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
List studentList = mapper.getStudentList();
for (Student student : studentList) {
System.out.println(student);
}
sqlSession.close();
}
也可以在sql查询起别名使查询出来的列名和属性名一致
4.2 自定义别名
定义自定义类型的别名
1)在mybatis主配置文件中定义,使
2)可以在resultType中使用自定义别名
4.3 模糊查询
1.在接口中编写方法
//模糊查询
public List getStudentByLike(String name);
2.编写sql
3.在测试类中运行
@Test
public void getStudentByLike(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
List studentList = mapper.getStudentByLike("%张%");
for (Student student : studentList) {
System.out.println(student);
}
sqlSession.close();
}
5.动态sql
动态sql:sq1的内容是变化的,可以根据条件获取到不同的sql语句。
主要是where部分发生变化。
动态sql的实现,使用的是mybatis提供的标签,
5.1 动态sql之if标签的使用
-
是判断条件的,
语法
部分sql语句
-
用来包含多个 的,当多个if有一个成立的, 会 自动增加一个where关键字,
并去掉if中多余的and,or等。 -
循环java中的数组,list集合的。 主要用在sql的in语句中。
实现
1.在接口中编写方法
//使用动态sql标签查询学生信息
public List getStudentByIf(Map map);
2.编写sql语句
3.在测试类中运行
@Test
public void getStudentByIf(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
HashMap
5.2 动态sql之where标签的使用
1.在接口中编写方法
//使用动态sql标签查询学生信息
public List getStudentWhere(Map map);
2.编写sql语句
3.在测试类中运行
@Test
public void getStudentWhere(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
HashMap
5.3动态sql之foreach标签的使用
collection:表示接口中的方法参数的类型,如果是数组使用array,如果是list集合使用list
item:自定义的,表示数组和集合成员的变量
open:循环开始是的字符
close :循环结束时的字符
separator :集合成员之间的分隔符
1.在接口中编写方法
//使用动态sql标签查询学生信息
public List getStudentForeach(List list);
2.编写sql
3.在测试类中测试
@Test
public void getStudentForeach(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
List list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
List studentList = mapper.getStudentForeach(list);
for (Student student : studentList) {
System.out.println(student);
}
}
5.4 动态sql之代码片段
使用
6.mybatis-config.xml主配置文件说明
6.1 数据库属性配置文件
1.数据库的属性配置文件:把数据库连接信息放到-一个单独的文件中。和mybatis主配置文件分开。
目的是便于修改,保存,处理多个数据库的信息。
1)在resources 目录中定义一个属性配置文件,xxxx . properties , 例如jdbc . properties
在属性配置文件中,定 义数据,格式是key=value
key:
一般使用.做多级目录的。
例如jdbc . mysql . driver,jdbc. driver, mydriver
jdbc . driver=com . mysql. jdbc . Driver
jcbc. url=jdbc :mysql//. .. ..
jdbc. username= root
jdbc . password= 123456
2)在mybatis的主配置文件,使用
在需要使用值的地方,$ {key}
db.properties:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=cjj17879392776
在mybatis-config.xml配置文件中导入使用
6.2 指定多个mapper文件的方式
第一种方式:
···
第二种方式
7.扩展
1. PageHelper分页使用步骤
1.在maven中导入PageHelper的依赖
com.github.pagehelper
pagehelper
5.1.10
2.在mybatis-config.xml文件中配置
3.测试使用
在接口中编写方法
//使用PageHelper分页
public List getStudentPageHelper();
编写sql
测试运行
@Test
public void getStudentPageHelper(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
PageHelper.startPage(1,4);
List studentList = mapper.getStudentPageHelper();
for (Student student : studentList) {
System.out.println(student);
}
}
```*