第一章 框架概述
1.1 软件开发常用架构
三层架构:界面层,业务层,数据访问层
1.2 JDBC编程的问题
重复操作多,开发效率多,需要自己处理查询过程和查询结果,对业务代码和数据库的操作混合在一起等
1.3 MyBatis概述
一个持久层框架,早期称为iBatis,代码开源在github
MyBatis是一个MyBatis Mapper Framerwork for Java(SQL映射框架)
1)sql mapper:sql映射
可以把数据表中的一行数据映射为一个java对象,操作这个对象就相当于操作数据库中的表
2)Data Access Objects(DAOs):数据访问,对数据库执行增删改查
MyBatis提供的功能:
1)提供了创建Connection,Statement,ResultSet的能力,不用开发人员再创建这些对象
2)提供了执行sql语句的能力,不用自己执行sql
3)提供了循环sql,把sql的结果转化为java对象,List集合的能力
4)提供了关闭资源的能力,关闭Connection,Statement,ResultSet资源
总结:开发人员需要做的就是提供sql语句。
MyBatis让开发人员集中精神写sql就可以了,不必自己创建连接,关闭连接等繁琐的操作
第二章 快速入门
实现步骤
- 新建的student表
- 加入maven的mybatis坐标,mysql驱动坐标
- 创建实体类,student 保存表中的一行数据
- 创建持久层的dao接口,定义操作数据库的方法
- 创建一个mybatis使用的配置文件
叫做sql映射文件:写sql语句的,一般一个表一个sql映射文件
这个文件是一个xml文件:文件创建在dao接口所在的目录,名字和接口名字相同 - 创建mybatis的主配置文件
一个项目就一个主配置文件,其中提供了数据库的连接信息和sql映射文件的位置信息 - 创建使用mybatis类
通过mybatis访问数据库
新建表
CREATE TABLE
student(id INT PRIMARY KEY,
`name` VARCHAR(50),
email VARCHAR(100),
age INT)
CHARSET = utf8;
INSERT INTO student VALUES
(1001, "李四", "lisi@qq.com", 20),
(1002, "张三", "zhangsan@sina.com", 28);
添加依赖到pom.xml
<!-- mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- 由于不再resources的非java文件不会被扫描,需要添加配置将与dao同目录下的文件赋值到target目录中-->
<build>
<resources>
<resource>
<directory>src/main/java</directory><!-- 文件所在的目录-->
<includes><!-- 包括目录下的.properties和.xml文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
创建实体类:
public class Student {
private Integer id;
private String name;
private String email;
private Integer age;
public Student(Integer id, String name, String email, Integer age) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
}
public Student() {
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", age=" + 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;
}
}
创建持久层的dao接口
package com.learn.dao;
import com.learn.domain.Student;
import java.util.List;
/**
* @author wuminggao
* @create 2020-07-13-下午2:19
*/
public interface StudentDao {
//获取所有的student组成的集合数据
public List<Student> getAllStudent();
}
在与dao相同目录下创建sql映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!--指定约束文件的
mybatis-3-mapper.dtd是约束文件的名称,扩展名是dtd的
用来限制和检查,出现在当前文件中出现的标签,属性,必须符合mybatis的要求
-->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--mapper是当前文件的跟标签,是必须有的
namespace:命名空间,是一个唯一值,可以是自定义的字符串
要求使用dao接口的全限定名称
在当前文件中,可以使用特定的标签,表示数据库的特定操作
<select:>查询语句
<update:>更新语句
<insert:>插入语句
<delete:>删除语句
select:表示查询操作
属性的id:你要执行的sql语法的唯一标志,mybatis会使用这个id的值来找到要执行的sql语句
可以自定义,但是要求使用接口中的方法名称
resultType表示结果类型,是sql语句执行后得到的resultSet,遍历这个ResultSet得到的java对象的类型
值写的是类型的全限定名称
-->
<mapper namespace="com.learn.dao.StudentDao">
<select id="getAllStudent" resultType="com.learn.domain.Student">
select id, `name`, email, age from student
</select>
</mapper>
在resources目录下创建mybatis的主配置文件
<?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">
<!--
当前文件是mybatis的主配置文件
主要定义了数据库的配置信息,sql映射文件的位置
同样开头的
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
是约束文件,mybatis-3-config.dtd是约束文件的名称
configuration是配置文件的跟标签
-->
<configuration>
<!-- 环境配置:数据库的连接信息
environments中的default属性的值必须和某个environment的id一样
-->
<environments default="mydev">
<!-- environment:是一个数据库信息的配置,环境
id:一个唯一值,自定义,表示环境的名称
-->
<environment id="mydev">
<!--
transactionManager:mybatis的事务类型
type的值有两个:JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)
dataSource表示数据源,连接数据库的
type:POOLED(表示使用数据库连接池)
-->
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--
properties属性定义了mybatis与数据库的连接信息
name为driver url username password是固定的,不能自定义
value
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true
-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--
mappers表示sql映射文件的位置
每个mapper标签制定一个文件的位置,从类路径开始的路径信息
target/classes(类路径)/ 下的文件位置
-->
<mappers>
<!-- <mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
<mapper resource="com/learn/dao/StudentDao.xml"></mapper>
</mappers>
</configuration>
创建使用mybatis类,访问数据库
public class MyTest {
public static void main(String[] args) throws IOException {
//访问mybatis读取student数据
//1. 定义mybatis的主配置文件的名称
String config = "mybatis.xml";
//2. 读取这个config表示的配置文件
InputStream inputStream = Resources.getResourceAsStream(config);
//3.创建sqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//4.创建sqlSessionFactory对象
SqlSessionFactory factory = builder.build(inputStream);
//5.获取SqlSession对象,从SQLSessionFactory中获取sqlSession
SqlSession sqlSession = factory.openSession();
//6.指定要执行的sql语句的标志,sql映射文件中的namespace + "." + 标签的id值
String sqlId = "com.learn.dao.StudentDao.getAllStudent";
//7.执行sql语句,通过sqlId找到语句
List<Student> students = sqlSession.selectList(sqlId);
//8.输出结果
students.forEach(System.out::println);
//9.关闭sqlSession对象
sqlSession.close();
}
}
使用占位符执行插入操作
<insert id="insertStudent">
insert into student values (#{id}, #{name}, #{email}, #{age})
</insert>
开启日志功能:
在mybatis.xml中加入
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
- 主要类的介绍
1)Resources类:MyBatis中的一个类,读取主配置文件,创建输入流
InputStream inputStream =
Resources.getResourceAsStream(config);
2)SqlSessionFactoryBuilder类:创建SqlSessionFactory对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
3)SqlSessionFactory:重量级对象,程序创建一个实例耗时比较长,使用资源比较多,在整个项目中有一个就够用了。
SqlSessionFactory是一个接口,实现类有DefaultSqlSessionFactory
SqlSessionFactory作用:获取SqlSession对象,SqlSession sqlSession = factory.openSession();
openSession()方法说明:
openSession()无参数方法,获取的是非自动提交事务的SqlSession对象
openSession(boolean )有参数的,设置为true,则获取自动提交事务的SqlSession
4)SqlSession接口:接口定义了很多操作数据的方法
例如:selectOne(),selectList(),insert(),update(),delete(),commit(),rollback()
接口的默认实现类DefaultSqlSession
使用要求:SqlSession对象不是线程安全的,需要在方法内部使用,在执行sql语句之前,使用openSession()获取SqlSession对象,在执行完sql语句后,需要关闭它,执行close方法,这样能保证它的使用是线程安全的。
第三章 MyBatis框架Dao代理
3.1 使用MyBatis的动态代理
在定义好DAO接口和mapper映射文件后,在测试类中添加方法
@Test
public void testStudentDao(){
/**
* 使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口)
* getMapper获取接口的实现类对象
*
*/
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<Student> students = studentDao.selectStudents();
students.forEach(System.out::println);
sqlSession.close();
}
即使用sqlSession.getMapper(dao接口.class )通过动态代理创建接口实现类,调用实现类的方法完成CRUD
3.2 如何把参数传入mapper映射文件的sql语句中
1)parameterType: 写在mapper文件中的一个属性。表示dao接口中方法的参数的数据类型。
例如StudentDao接口,public Student selectStudentById(Integer id)
首先在mappper文件中添加
<mapper namespace="com.learn.dao.StudentDao">
<select id="selectStudentById" parameterType="java.lang.Integer" resultType="com.learn.domain.Student">
select id, name, email, age from student where id = #{id};
</select>
</mapper>
parameterType的值是java的数据类型全限定名称或者是mybatis定义的别名
注意:parameterType不是强制需要写的,mybatis通过反射机制能够发现接口参数的参数类型,一般不写。
3.3 将一个简单类型的参数传入mapper文件
简单类型:基本数据类型+字符串类型
在mapper文件获取简单类型的一个参数的值,使用 #(任意字符) eg: #
实际上是JDBC中的PreparedStatement的预编译语句中的占位符 '?',然后使用参数填充占位符。
3.4 传入多个参数到mapper文件
3.4.1 使用@Param命名参数
现在StudentDao接口中存在一个方法
List<Student> selectMultiParam(@Param("myName") String name,
@Param("myAge") Integer age);
使用 @Param("参数名") 形参
mapper文件:
<select id="selectMultiParam" resultType="com.learn.domain.Student">
select id, name, email, age from student where name = #{myName} or age = #{myAge};
</select>
3.4.2 传递对象
在mapper映射文件中,写占位符时按如下格式写(很少使用):
#{对象的属性名, javaType=Java中类型名称, jdbcType=数据库中数据类型}
eg:#{paramName, javaType=java.lang.String, jdbcType=VARCHAR}
简化方式:#{属性名},javaType和jdbcType通过mybatis框架反射自动获取
现在StudentDao接口中存在一个方法
List<Student> selectMultiByQueryParam(QueryParam queryParam);
//传递一个自定义类型的对象
public class QueryParam {
private String paramName;
private Integer paramAge;
。。。下面是set和get方法,省略
}
mapper映射文件:
<select id="selectMultiByQueryParam" resultType="com.learn.domain.Student">
select id, name, email, age from student where name = #{paramName} or age = #{paramAge};
</select>
3.4.3 按位置传递参数(了解)
在MyBatis3.3版本及之前通过#{0},#{1}方式,从MyBatis3.4开始使用#方式。
3.4.4 使用map传递参数(了解)
形参写为map,在mapper映射文件使用#获取存放的值
3.5 #和$的区别
井号#的意思:占位符,告诉MyBatis使用实际的参数填充占位符,并且使用PreparedStatement对象执行SQL语句,这样做更安全,更迅速,通常是首选做法
$的意思:告诉MyBatis使用$包含的”字符串“替换所在位置,使用Statement把SQL语句和${}的内容连接起来,主要用在替换表名,列名,不同列排序等操作
$就相当于Statement的拼串处理,存在sql注入问题
#和$的区别
1)#使用?在sql语句中做占位符,使用PreparedStatement执行sql,效率高
$相当于字符串拼串,使用Statement执行sql,效率低
2)#能避免sql注入问题,$不可以
3.6 MyBatis的输出结果
MyBatis执行了sql语句,得到java对象
1)resultType结果类型是自定义对象,指sql语句执行完毕后,数据转为java对象。
处理流程:
->MyBatis执行sql语句后,然后调用类的无参构造器,创建实例
->MyBatis将查询结果ResultSet的指定列值使用set方法注入实例中的属性,注意查询列名和属性名需要一致
2)resultType返回简单类型,比如查询行数,返回整型
<select id="selectCount" resultType="int">select count(*) from student;</select>
此处resultType的值int是java.lang.Integer的别名
定义自定义类型的别名方法:在主配置文件使用typeAlias标签,定义位置在settings标签后面
使用typeAlias指定全限定名称type和其别名alias
<!-- 定义别名-->
<typeAliases>
<typeAlias type="com.learn.domain.Student" alias="stu"/>
</typeAliases>
或者使用package标签,表示该包下所有类以其类名作为别名
<typeAliases>
<package name="com.learn.domain"/>
</typeAliases>
注意!不建议使用别名,可能出现冲突
3)方法返回结果是一个Map类型
返回Map时,框架将列名作为键,查询得到的值作为键的值,返回这个Map。同时要求查询记录只有一行。
3.7 使用resultMap结果映射
指定列名和java对象的属性对应关系,用在想要自定义哪个列赋值给哪个属性时,或者当列名和属性列不一样时。
<!-- id自定义名称,type表示要转换的对象-->
<resultMap id="studentMap" type="com.learn.domain.Student">
<!-- id标签是主键列 column是列名 property是java类型的属性名
result标签是非主键列
-->
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
<result column="email" property="email"/>
</resultMap>
还有另一种解决方式,在sql语句给字段取别名
<select id="selectAllStudents2" resultType="com.learn.domain.Student2">
select id anId, name aName, email anEmail, age anAge from student;
</select>
3.8 模糊查询
1)在java代码指定like的内容,将内容作为参数传入
<select id="selectLikeOne" resultType="com.learn.domain.Student">
select id, name, email, age from student where name like #{name};
</select>
eg:调用方法stuendtDao.selectLikeOne("%李%")
2)在mapper文件中拼接like的内容
<select id="selectLikeOne" resultType="com.learn.domain.Student">
select id, name, email, age from student where name like "%" #{name} "%";
</select>
不够灵活,不推荐
第四章 MyBatis框架动态SQL
动态SQL:sql的内容是变化的,可以根据条件获取到不同的sql语句,主要是where部分发生变化。
动态SQL的实现使用的是MyBatis提供的标签
4.1 环境准备
4.2 动态SQL之<if>
<!--
if标签的使用
使用参数java对象的属性值作为判断条件,直接使用属性=xxx值
-->
<select id="selectStudentIf" resultType="com.learn.domain.Student">
select id,name,age,email from student
where 1=1
<if test="name != null and name != '' ">
name = #{name}
</if>
<if test="age > 0">
or age >= #{age}
</if>
</select>
这个存在问题,前后多个if判断时的逻辑运算符and和or可能会语法错误!
4.3 动态SQL之<where>
where 标签是用来包含if标签的,当多个if有一个成立的时候,where会自动增加一个where关键字,并去掉if中多余的and,or
<select id="selectStudentWhere" resultType="com.learn.domain.Student">
select id,name,age,email from student
<where>
<if test="name != null and name != '' ">
name = #{name}
</if>
<if test="age > 0">
or age >= #{age}
</if>
</where>
</select>
4.4 动态SQL之<foreach>
foreach用来做循环处理,循环java中的数组或者list集合,主要用在sql的in子句中
首先认识foreach标签的属性
<foreach collection="" item="" open="" close="" separator="">
</foreach>
collection:表示接口中的方法参数的类型,如果是数组使用array,如果是list集合使用list
item:自定义的,表示数组和集合成员的遍历
open:循环开始时的字符
close:循环结束时的字符
separator:集合成员之间的分隔符
接口中的方法:
List<Student> selectForEachOne(List<Integer> idList);
mapper映射文件:
<select id="selectForEachOne" resultType="com.learn.domain.Student">
select * from student where id in
<foreach collection="list" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>
传入的集合可以是对象集合,元素item是对象,如下,传入的参数是一个Student对象组成的list集合,使用对象.属性获取值
<select id="selectForEachOneByStudentId" resultType="com.learn.domain.Student">
select * from student where id in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu.id}
</foreach>
</select>
4.5 动态SQL之代码片段
可以重复使用的sql语句
使用sql标签定义代码片段,id是自定义的代码片段id
<sql id="selectAllColumns">
select id,name,age,email from student
</sql>
使用只需要在需要的地方include进去即可,refid填写代码片段id
<select id="selectForEachOneByStudentId" resultType="com.learn.domain.Student">
<include refid="selectAllColumns"/> where id in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu.id}
</foreach>
</select>
第五章 MyBatis配置文件
5.1 主配置文件
以这个主配置文件为例
<?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>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
定义别名
<typeAliases>
<!-- <typeAlias type="com.learn.domain.Student" alias="stu"/>-->
<package name="com.learn.domain"/>
</typeAliases>
<environments default="mydev">
<environment id="mydev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/learn/dao/StudentDao.xml"></mapper>
</mappers>
</configuration>
settings:是一些全局配置,可以参考官方文档
environments:是一些环境配置,其中transactionManager是提交事务,回滚事务的方式,有几个值:1)JDBC: 表示mybatis底层使用JDBC中的Connection对象的commit,rollback 2)MANAGED:表示把mybatis的事务处理委托给其他的容器(例如服务器软件,spring框架)
5.2 dataSource标签
dataSource:表示数据源,java体系中,规定实现了javax.sql.DataSource接口的都是数据源。数据源表示Connection对象
dataSoruce标签有type属性:1)POOLED,使用连接池,mybatis会创建PooledDataSource类。2)UNPOOLED,不使用连接池,每次执行sql语句都创建连接并关闭连接。3)JNDI:java命名和目录服务(windows注册表)
5.3 事务
5.4 使用数据库属性配置文件
把数据库连接信息放到一个单独的文件中,和mybatis主配置文件分开,便于修改,保存,处理多个数据库的信息
1)在resources目录中定义一个properties文件
配置文件中,定义数据,格式是key-value
key:一般使用多级目录的表示法。
例如 jdbc.mysql.driver
2)在主配置文件使用${key}
的方式获得配置文件中的值
5.5 typeAliases(类型别名)
typeAliases:配置类的别名,有两种方式
package和typeAlias
<typeAlias type="com.learn.domain.Student" alias="stu"/>
<package name="com.learn.domain"/>
5.6 mapper(映射器)
如果有多个映射文件,需要都进行指定
方式一:手动指定多个mapper文件
<mappers>
<mapper resource="com/learn/dao/StudentDao.xml"></mapper>
<mapper resource="com/learn/dao/xxxx2Dao.xml"></mapper>
<mapper resource="com/learn/dao/xxxx1Dao.xml"></mapper>
</mappers>
方式二:使用包名
这种方式中,所有xml文件一次都全部加载给mybatis
需要mapper文件名称需要和对应的接口名称一样,区分大小写
还需要mapper文件和dao接口需要在同一目录
<mappers>
<package name="com.learn.dao"/>
</mappers>
第六章 扩展
6.1 PageHelper
用于做数据分页
1)添加maven依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
2)在主配置文件的environment前添加
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
3)在需要分页的查询前调用PageHelper.startPage(3, 3);
第一个参数pageNum表示第几页,第二个参数pageSize表示一页有多少条记录
Comments | 0 条评论