Mybatis
Mybatis的第一个程序
1.pom文件
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
2.配置MapperConfig.xml
<?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>
<properties resource="jdbc.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driverClass}"/>
<property name="url" value="${jdbcUrl}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- resource:扫描的是xml文件-->
<!-- class:扫描的是xml文件-->
<mapper resource="com/xukai/Mapper/UserMapper.xml"/>
</mappers>
</configuration>
3.Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xukai.dao.Userdao">
<select id="Getall" resultType="com.xukai.entity.User">
select * from user_table
</select>
<select id="getUser" parameterType="java.lang.String" resultType="com.xukai.entity.User">
select * from user_table where user = #{user}
</select>
<insert id="AddUser" parameterType="com.xukai.entity.User" >
insert into user_table (user,password,balance)values(#{user},#{password},#{balance});
</insert>
<delete id="UpdateUser" parameterType="com.xukai.entity.User" >
update user_table set user=#{user},password=#{password},balance=#{balance}
</delete>
<delete id="DeleteUser" parameterType="java.lang.String" >
delete from user_table where user=#{user}
</delete>
</mapper>
// 1.创建一个SqlSessioFactory
SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
// 2.把MyBatis配置文件转成一个流
InputStream ips = Resources.getResourceAsStream("mybatis-config.xml");
// 3.构建SQLSessionFactory
SqlSessionFactory sqlSessionFactory = sfb.build(ips);
// 4.通过SQLSessionFactory创建SQLSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 这是IBatis中的写法
// 调用返回一个结果集的sql语句
Map<String,Object> map = new HashMap<>();
map.put("name","admin");
map.put("pw","admin");
User user = (User)sqlSession.selectOne("com.qf.dao.IUserDao.getUserById", map);
// sqlSession.selectList();
sqlSession.insert("com.qf.dao.IUserDeao.addUser",new User());
// sqlSession.delete()
System.out.println(user);
Mybatis中的三种写法
1.通过映射器
-
通过xml
-
通过注解
注解的话MapperConfig.xml中需要把<Mappers>换出calss扫描
2.直接调用sql(Iatis中的特有写法)官网有写法https://mybatis.org/mybatis-3/zh/getting-started.html
日志
Mybatis中也有内置日志
STDOUT_LOGGING (标准日志输出)
1.MapperConfig.xml文件配置
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
Log4j
- Log4j是Apache的一个开源项目
- 通过使用Log4j,我们可以控制日志信息输送的目的地:控制台,文本,GUI组件…
- 我们也可以控制每一条日志的输出格式;
- 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
1.相应的jar
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2.log4j的配置文件
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
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
获取方法参数/别名设置
获取参数
-
按照索引
-
按照名称
-
Map获取.根据key获取问value就是那个对应的值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-danR4l54-1631536799134)(image/image-20210416110800219.png)]
-
对象自动属性获取
别名设置
<typeAliases>
<!--typeAlias:这是指定一个类名的别名-->
<!--package:这是指定一个包下的类起别名,默认就是类型小写.可以通过-->
<typeAlias type="com.xukai.entity.User" alias="user"/>
<package name="com.xukai.ent ity"/>
</typeAliases>
在这个包下设置了别名也可以修改别名,用注解@Alias
字段和属性映射关系
@Param
绑定的是mysql里面的字段
ResultMap
将数据和实体类里面的关系映射起来
As
别名
主键回填
-
xml配置
<!-- 主键回填: useGeneratedKeys:true是否开启主键回填 keyProperty:回填到哪个属性里面 --> <insert id="AddStudent" useGeneratedKeys="true" keyProperty="id" > insert into user(name,password,address,phone)values(#{name},#{password},#{address},#{phone}) </insert>
-
测试:
#和$区别
Mybatis动态sql
动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句.
-------------------------------
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
-------------------------------
if
Student GetStudentById(@Param("id") Integer id,@Param("name") String username);
<!--
Mybatis的动态sql练习,test里面为真的话就会加上if里面的sql
if里面的test是个判断,name是传过来的字段
-->
<select id="GetStudentById" resultType="student">
select * from user
where id = #{id}
<if test="name != null and name != ''">
and name=#{name}
</if>
</select>
where
Student GetStudentByMany(@Param("id") Integer id,@Param("name") String name);
<select id="GetStudentByMany" resultType="student">
select *
from user where
//otherwise:如果都不匹配,那么久会加上这里面的 .就相当于java中的switch
<choose>
<when test="name != null">
name = #{name}
</when>
<when test="id != null">
id = #{id}
</when>
<otherwise>
id = 1;
</otherwise>
</choose>
</select>
where
Student GetStudentByWhere(@Param("id") Integer id,@Param("name") String name);
<!--where标签会替换自动生成where-->
<select id="GetStudentByWhere" resultType="student">
select * from user
<where>
<if test="id != null">
id = #{id}
</if>
<if test="name != null and name != ''">
and name=#{name}
</if>
</where>
</select>
trim
Student GetStudentByTrim(@Param("id") Integer id,@Param("name") String name);
<!-- trim:
prefix:在之前添加的内容
prefixOverrides:前缀覆盖
suffix:在之后添加的内容
-->
<select id="GetStudentByTrim" resultType="student">
select * from user
<where>
<trim prefix="and" prefixOverrides=",">
<if test="id != null">
, id = #{id}
</if>
<if test="name != null and name != ''">
, name=#{name}
</if>
</trim>
</where>
</select>
Foreach
List<Student> GetListStudent(List<Integer> id);
<!--foreach:
collection:遍历的属性 list,map,array,
item:就是一个变量
open:开头,只会掉用一次
close:结束循环,只会调用一次
separator:每次循环调用一次,
-->
<select id="GetListStudent" resultType="student">
select *
from user
where id in
<foreach item="ids" collection="list" open="(" close=")" separator=",">
#{ids}
</foreach>
</select>
Set
set标签和trim标签一样,会自动添加set关键字,过滤多余的逗号
缓存
- 临时数据,
- 提高效率,在本地磁盘上面去查询,不用再去连接数据库
使用缓存的好处
- 减少开销
- 提高效率
Mybatis缓存
- MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。
- MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存
- 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
- 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
- 为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
一级缓存
一级缓存也叫本地缓存,SqlSession级别的缓存:
- 与数据库同一次会话期间查询到的数据会放在本地缓存中。
- 以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;
测试:
@Test
public void TestCache(){
Student student = studenDao.GetStudentById(4);
System.out.println("cache========= = cache");
Student student1 = studenDao.GetStudentById(4);
System.out.println("student==student1 = " +(student == student1));
}
查看日志
一级缓存Mybatis是默认开启的
一级缓存缓存失败的四种情况:
一级缓存是SqlSession级别的缓存,是一直开启的,我们关闭不了它;
一级缓存失效情况:没有使用到当前的一级缓存,效果就是,还需要再向数据库中发起一次查询请求!
- Sqlsession不同
- 每个sqlsession中的缓存相互独立
- Sqlsession相同,查询条件不同
- 缓存不一样,数据不一样,找不到缓存。
- Sqlsession相同,两次查询之间执行了增删操作
- 因为增删操作可能会对当前数据产生影响
- Sqlsession相同,手动清除一级缓存
- 一级缓存就是一个map(debug的时候可以发现,里面有方法的缓存)
二级缓存
二级缓存需要手动开启(Namespaces)级别
所有的实体类先实现序列化接口(将实体类存在本地,也是使用map储存)
- 在MapperConfig开启
<setting name="cacheEnabled" value="true"/>
-
在相对于的mapper文件中开启缓存
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false"> <!-- diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下: user.home – 用户主目录 user.dir – 用户当前工作目录 java.io.tmpdir – 默认临时文件路径 --> <diskStore path="./tmpdir/Tmp_EhCache"/> <!-- defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。 --> <defaultCache eternal="false" maxElementsInMemory="10000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="1800" timeToLiveSeconds="259200" memoryStoreEvictionPolicy="LRU"/> <!-- 开启缓存--> <cache name="cloud_user" eternal="false" maxElementsInMemory="5000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="1800" timeToLiveSeconds="1800" memoryStoreEvictionPolicy="LRU"/> <!-- name:缓存名称。 maxElementsInMemory:缓存最大数目 maxElementsOnDisk:硬盘最大缓存个数。 eternal:对象是否永久有效,一但设置了,timeout将不起作用。 overflowToDisk:是否保存到磁盘,当系统当机时 timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。 timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。 diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false. diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。 diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。 memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。 clearOnFlush:内存数量最大时是否清除。 memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。 FIFO,first in first out,这个是大家最熟的,先进先出。 LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。 LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。 --> </ehcache>
测试:
二级缓存默认会在insert;update;delete;操作后刷新缓存;可以手动不刷新缓存
总结:
分页
分页插件
1.jar
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
2.MapperConfig.xml
配置插件
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="param1" value="value1"/>
</plugin>
</plugins>
3.使用:
Limit
List<Student> getListStudentLimit(Map<String,Integer> map);
Mapper.xml
<select id="getListStudentLimit" resultMap="StudentMap">
select * from user limit #{startIndex},#{PageSize}
</select>
防止出现src下面的mapper文件编译不出来
<!-- 防止src下面的xml文件编译不到-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
Mybatis中的四大对象
Excutor
Mybatis中的执行器,用于CURD
StatementHandel
处理数据库对象用于执行SQL
ResultSetHandel
处理SQL返回的结果集
ParamenterHandel
dentLimit" resultMap=“StudentMap”>
select * from user limit #{startIndex},#{PageSize}
[外链图片转存中...(img-nrW3LkPp-1631536799155)]
# 防止出现src下面的mapper文件编译不出来
```xml
<!-- 防止src下面的xml文件编译不到-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
```
# Mybatis中的四大对象
## Excutor
Mybatis中的执行器,用于CURD
## StatementHandel
处理数据库对象用于执行SQL
## ResultSetHandel
处理SQL返回的结果集
## ParamenterHandel
用户处理SQL参数对象