MyBatis温故而知新
目的:巩固基础知识,加深记忆
文章目录
前言
例如:经济基础决定上层建筑,上层建筑反作用于经济基础。技术亦是同理。
一、Mybatis是什么?
是一款优秀的持久层框架。
1.持久化
即可以将数据永久保存在存储设备中(如:磁盘)。持久化主要应用是将内存对象存储在数据库中,或者磁盘文件,xml数据文件中等。
JDBC是持久化机制,文件IO也是持久化机制
2.为什么要持久化
因为内存一旦断电,就会丢失数据。
内存有容量限制,不可能一直呆在内存中,需要持久化缓存到外存。
3.持久层(dao)
完成持久化工作的代码块(dao层)。持久化的过程大多通过各种关系型数据库完成。
二、搭建环境
1.引入依赖
代码如下(示例):
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
2.配置文件
mybatis-config.xml:
<configuration>
<environments default="development">
<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/mybatis?
useSSL=true&useUnicode=true& characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/kuang/dao/userMapper.xml"/>
</mappers>
</configuration>
该处使用的url网络请求的数据。
3.工具类
import java.io.InputStream;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream =
Resources.getResourceAsStream(resource);
sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession连接
public static SqlSession getSession(){
return sqlSessionFactory.openSession();
}
}
三.配置解析
核心配置文件:mybatis-config
配置属性如下:
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
注意以上元素节点的顺序!顺序不对会报错。一般会提示!
1. environments 元素
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<!-- transactionManager 事务管理器
type=JDBC | MANAGED
-->
<property name="..." value="..."/>
</transactionManager>
<dataSource type="POOLED">
<!--
datasource type分为三个type="[UNPOOLED|POOLED|JNDI]")
UNPOOLED:这个数据源实现只是每次请求时打开和关闭连接。
POOLED:数据源实现利用"池"的概念讲JDBC对象组织起来,这是一种使得并发web应用快速响应请求的处理方式
JNDI:这种数据源为了配合Spring使用,容器可以集中在外部配置数据源
-->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
可以配置多套数据库,使用default指定默认,通过id
2.mappers 元素
定义映射的sql文件。
方式一:使用类路径的资源引用
<mappers>
<mapper resource="com/dfh/userMapper.xml"/>
</mappers>
方式二:使用完全限定资源定位符
<mappers>
file后面至少两个// 可以达到访问根目录
<mapper url="file///src/main/java/com/dfh/userMapper.xml"/>
</mappers>
方式三:使用映射器接口实现类的完全限定类名
需要配置文件名称和接口名称一致,并且位于同一目录下
<mappers>
<mapper class="com.dfh.mapper.userMapper"/>
</mappers>
方式四:将包内的映射器接口实现全部注册为映射器
但是需要配置文件名称和接口名称一致,并且位于同一目录下
<mappers>
<mapper package="com.dfh.mapper"/>
</mappers>
3、利用properties文件优化配置
1.建立db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useSSL=true&useUnicode=true&characterEncoding=utf8
username=root
pwd=root
2.修改配置文件
<configuration>
<!--导入properties文件-->
<properties resource="db.properties"/>
<environments default="test">
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${pwd}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
4.typeAliases
类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
<!--配置别名,注意顺序-->
<typeAliases>
<typeAlias type="com.kuang.pojo.User" alias="User"/>
</typeAliases>
<!--方式二 指定包名,如果类上没有用注解@Alias("user")规定,默认首字母小写作为别名 -->
<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>
5.日志
Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种工具:
SLF4J
Apache Commons Logging
Log4j 2
Log4j
JDK logging
具体选择哪个日志实现工具由MyBatis的内置日志工厂确定。它会使用最先找到的(按上文列举的顺序
查找)。 如果一个都未找到,日志功能就会被禁用。
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
使用LOG4J
//首先导包
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
log4j.properties 配置文件
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
然后到数据库配置文件中修改setting值
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
最后就可以使用LOG4J输出
private static Logger logger=Logger.getLogger(test.Class);
四、生命周期和作用域
1.Mybatis执行流程图
理解:
SqlSessionFactoryBuilder 的作用在于创建 SqlSessionFactory,创建成功后,SqlSessionFactoryBuilder 就失去了作用,所以它只能存在于创建 SqlSessionFactory 的方法中,而不要让其长期存在。因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是
局部方法变量)。
SqlSessionFactory 可以被认为是一个数据库连接池,它的作用是创建 SqlSession 接口对象。因为MyBatis 的本质就是 Java 对数据库的操作,所以 SqlSessionFactory 的生命周期存在于整个MyBatis 的应用之中,所以一旦创建了 SqlSessionFactory,就要长期保存它,直至不再使用MyBatis 应用,所以可以认为 SqlSessionFactory 的生命周期就等同于 MyBatis 的应用周期。
由于 SqlSessionFactory 是一个对数据库的连接池,所以它占据着数据库的连接资源。如果创建多个 SqlSessionFactory,那么就存在多个数据库连接池,这样不利于对数据库资源的控制,也会导致数据库连接资源被消耗光,出现系统宕机等情况,所以尽量避免发生这样的情况。
因此在一般的应用中我们往往希望 SqlSessionFactory 作为一个单例,让它在应用中被共享。所以说 SqlSessionFactory 的最佳作用域是应用作用域。
如果说 SqlSessionFactory 相当于数据库连接池,那么 SqlSession 就相当于一个数据库连接(Connection 对象),你可以在一个事务里面执行多条 SQL,然后通过它的 commit、rollback等方法,提交或者回滚事务。所以它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给 SqlSessionFactory,否则数据库资源就很快被耗费精光,系统就会瘫痪,所以用 try…catch…finally… 语句来保证其正确关闭。所以 SqlSession 的最佳的作用域是请求或方法作用域。
五、 #和$的区别
#{}的作用是替换预编译语句中的占位符
${}的作用是直接进行字符替换
简明的解释:
#{}是预编译处理,$ {}是字符串替换(当做占位符来用)。
mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的
set方法来赋值;
例子/:select * from user where id=#{id}
#{} 可以根据所需类型进行符值,如果是字符就是‘12’,如果是整型就是id=12
mybatis在处理 $ {} 时,就是把 ${} 替换成变量的值。
而¥{id}不进行数据类型匹配,直接替换掉。
所以如果id是字符类型,sql语句应该写成 select * from user where id='${id}'
使用 #{} 可以有效的防止SQL注入,提高系统安全性。
在某些特殊场合下只能用${},不能用#{}。例如:在使用排序时ORDER BY ${id},
如果使用#{id},则会被解析成ORDER BY “id”,这显然是一种错误的写法。
**到此结束即可**
六、ResultMap 的使用
1.多对一
设定学生和老师两个类,学生与老师的关系是多对一,多个学生对应一个老师。
建学生实体类和dao层接口
@Data
public class Student {
private int id;
private String name;
//多个学生可以是同一个老师,即多对一
private Teacher teachers;
}
接口方法
public List<Student> getStudents();
然后建对应Mapper文件
<resultMap id="StudentTeacher" type="Student">
<id property="id" column="sid"/>
<result property="name" column="sname" />
<association property="teachers" javaType="Teacher" >
<result property="name" column="tname"/>
</association>
</resultMap>
<select id="getStudents" resultMap="StudentTeacher">
select s.id sid, s.name sname , t.name tname
from student s,teacher t where s.tid=t.id
</select>
2.一对多
一个老师拥有多个学生
编写类
@Data
public class Student {
private int id;
private String name;
private int tid;
}
@Data
public class Teacher {
private int id;
private String name;
//一个老师多个学生
private List<Student> students;
}
然后写接口,建立对应Mapper文件,此处省略,主要是看mapper
<resultMap id="ST" type=teacher>
<id property="id" column="tid"/>
<result property="name" column="tname" />
<collection property="students" ofType="Student">
<result property="id" column="sid" />
<result property="name" column="sname" />
<result property="tid" column="tid" />
</colection>
</resultMap>
<select id="getTeacher" resultMap="ST">
select s.name sname ,t.name tname,t.id tid
from student s,teacher t
where s.tid=t.id and t.id=#{tid}
</select>
注意: JavaType和ofType都是用来指定对象类型的 JavaType是用来指定pojo中属性的类型 ofType指定的是映射到list集合属性中pojo的类型。
七 动态SQL
trim 属性
prefix:前缀覆盖并增加其内容
suffix:后缀覆盖并增加其内容
prefixOverrides:前缀判断的条件
suffixOverrides:后缀判断的条件
<insert id="insertUser" parameterType="User">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="name !=null and name!=''">name,</test>
<if test="phone!=null ">phone,</test>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="name !=null and name!=''">#{name},</test>
<if test="phone!=null ">#{phone},</test>
</trim>
</insert>
<update id="updateUser" parameterType="User">
update useri
<trim prefix="set" suffixOverrides=",">
<if test="name !=null and name!=''">name=#{name},</test>
<if test="phone!=null ">phone=#{phone},</test>
</trim>
where id=#{id}
</update>
foreach 循环语句
collection:指定输入对象中的集合属性
item:每次遍历生成的对象
open:开始遍历时的拼接字符串
close:结束时拼接的字符串
separator:遍历对象之间需要拼接的字符串
select * from blog where 1=1 and (id=1 or id=2 or id=3)
<select id="selectByIdList" resultType="User">
select * from user
<where>
<foreach collection="ids" item="id" open="(" close=")" separator="or">
id=#{id}
</foreach>
</where>
</select>
1164

被折叠的 条评论
为什么被折叠?



