学习mybatis时记录的笔记

********** Mybatis框架********

软件开发常用结构
spring mvc 是web开发的一个模式
数据视图控制器
三层架构
界面层,业务逻辑层,数据访问层。
1.界面层(html,jsp,servlet,)接收用户数,显示请求的处理结果,使用web页面和用户交互,手机app也是表示层
,用户在app中操作,业务逻辑在服务端处理。
2.业务逻辑层:接收界面层传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取数据。
3。数据访问层,与数据库打交道,主要实现对数据的增删改查,将数据库的数据提交给业务层。同时将业务层处理的数据保存到数据库。

//controller,service,dao
三层对应的包:
界面层:Controller(servlet)
业务逻辑层:service包(xxxservice类)
数据访问层:到包(xxxdao类)。

三层中类的交互
用户使用界面层-》业务逻辑层-》数据访问层(持久层)-》数据库(mysql)

三层对应的处理框架
界面层–》servlet–springmvc(框架)
业务逻辑层–service类–spring(框架)
数据访问层–dao类—mybatis(框架)持久层

2.框架
框架是一个舞台-一个模板。
模板:
1.规定来了号的条框,内容。
2.加入自己的东西。

框架是一个模块
1。框架中定义好了一些功能,这些功能都是可以用的。
2.可以加入项目中自己的功能,这些功能可以利用框架中写好的功能。

框架的定义。
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件实例间交互的方法。
框架是可悲应用开发者定制的应用骨架,模板。

框架是一个半成品软件,定义好了一些基础功能,加入你自己的一些功能就是完整的。基础功能是可重复使用的,可升级的。
框架Framework
框架的特点:1.框架一般不是全能的,不能做所有的事情。
2.框架是针对某一个领域有效,特长在某一个方面,比如mybatis做数据库操作,但是特不能做其他的。
3.框架是一个软件。

JDBC的缺陷:
代码较多,开发效率低。
2.需要关注Connection,Statement,Result对象的创建。
3. 对 ResultSet 查询的结果,需要自己封装为 List
4. 重复的代码比较多些
5. 业务代码和数据库的操作混在一起

注册驱动:
Class.forName("com.mysql.cj.jdbc.Driver)
获取连接通道
Connection con=DriverManager.getConnection(“jdbc:mysql://localhost:3306/bjpowernode”,“root”,“123456"”);
获取操作数据库对象
PerparStatement ps=con.perparstatement(sql)
执行sql并返回结果集
Result result=ps.executeUpdate();
mybatis***框架
mybatis是apache的一个开源项目Ibatis演变而来。代码在github上。
mybatis是mybatis sql mapper framework java (sql映射框架)
1)sql mapper:sql映射

可以把数据库表中的一行数据,映射为一个java对象。
一行数据可以看做是一个java对象。
一刚数据可以看做是一个java对象,操作这个对象,就相当于表中的数据。
2)Data Access Objects(Daos):数据访问

mybatis提供了哪些功能:
1.提供了创建Cononection,statement,resultset
2.提供了执行sql语句的能力,不用你执行sql
3.提供了循环sql,把sql的结果转为java对象,List集合的能力。
4.提供了关闭资源的能力,不用你关闭Connection,Statement,ResultSet

开发人员做的是:提供sql语句
最后是:开发人员提供sql语句-mybatis处理sql–开发人员得到List集合或java对象(表中的数据)
mybatis是一个sql映射框架,提供的数据库操作能力,增强的JDBC
使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet的
创建,销毁,sql的执行。

是一个基于java的持久层框架。
github,开发人员的社交平台。

实现步骤**
1.新建的student表
2.加入maven的mybatis坐标,mysql驱动的坐标
3.创建实体类,student,保存表中的一行数据的
4.创建持久层的dao接口,定义操作数据库的方法
5,。创建一个mybatis使用的配置文件
叫做sql映射文件:写sql语句,一般一个表一个sql映射文件,这个文件是xml文件。

<?xml version="1.0" encoding="UTF-8" ?> select * from Blog where id = #{id} 有一定属性(特征)和功能(行为)的就是对象 具有相同属性的对象就构成一个类 1)在接口所在的目录中。 2)文件名称和接口保持一致。 创建一个文本文件。以xml结尾 6:创建mybatis的主配置文件:一个项目就一个主配置文件。 主配置文件提供了数据库的连接信息和sql映射文件的位置信息 7.创建使用mybatis类: 通过mybatis访问数据库。

如果在target下找不到mabatis.xml文件
三种方法:1.在bulid中rebulid probject
2.在file中清除缓存
3.手动拖动。

日志:


类的介绍:
InputStream in = Resources.getResourceAsStream(config);
Resources:mybatis中的一个类,负责读取主配置文件。

2)SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactoryBuilder:创建sqlSessionFactory对象

创建sqlSessionFactory对象:
SqlSessionFactory factory = builder.build(in);
//SqlSessionFactory factory=new SelSessionBulider().bulid(in);
3)SqlSessionFactory:重量级对象,程序创建一个对象耗时比较长,使用资源比较多,在一个项目中,有一个就够了。
SqlSessionFactory是为了获取SqlSession
openSession()方法说明;
1.openSession();无参数的,获取是非自动
2.openSession(boolean);true自动提交
false不自动提交。

4)SqlSession:
SqlSession接口:定义了操作数据的方法 例如selectOne(),selectList(),update()等。
SqlSession接口的实现类DefaultSqlSession

使用要求:SqlSession对象不是线程安全的,需要在方法内部去使用在执行语句之前,使用openSession()获取SqlSession
在执行完sql语句之后,需要关闭它
执行sqlSession.close()。这样能保证线程安全。

*********Settings File and Code Templates添加模板 **********

<?xml version="1.0" encoding="UTF-8" ?> select * from student;

mybatis动态代理

1.dao对象,类型是studentDao 全限定名称是com.anyu.dao.StudentDao跟namespace一样。
2.方法名称跟mapper文件的id值一样
3.通过Dao中方法返回值可以确定mybatis要用的sqlSession的方法
如果返回值是list,调用的是sqlSession.selectlist()方法,如果返回值int 或是非list的看mapper文件中
标签是则会调用sqlsession的insert,update等方法。
mybatis的动态代理:mybatis根据dao的方法调用,获取执行sql语句的信息。
mybatis根据你的dao接口,创造出一个dao接口的实现类,并创建这个类的对象
完成sqlSession调用方法,访问数据库。

StudentDao dao=session.getMapper(StudentDao.class);

    //MybatisIntils my=new MybatisIntils();
//因为该类的静态方法是程序启动时自动放在内存中了的,是属于程序的公共内存(但只能访问),
// 而类名在这里你可以理解为命名空间。先通俗的分析下,我们把类看作是一个房子。房子里面有
// 家具,桌椅板凳之类的,房子里面还有人。 房子里面所有的人都应该是共有一套家具的。也就
// 是说,这些家具是唯一的,如果某个家具坏了,那么大家都用不了。 我们再看一看定义,java的
// 静态变量也叫做类变量,它开始于类的创建,结束于类的消亡。非静态变量叫做实例变量,它开始
// 于类的实例的创建,结束语类的实例的消亡。静态变量被所有实例所共享。也就是如上面的例子,
// 座椅板凳是类变量,它们是在房子被建好了之后就被添加放置进来,而且基本都是唯一的。人就相
// 当于实例,每个人都能用这些家具,但是如果家具一旦损坏,那就是坏了,或者你把某一个家具搬走,
// 那么所有的人都用不了这个家具,房子里也不存在这个家具了。 但是房子里可以进很多人,可以进张
// 三,也可以进李四。所以这些人就是类的实例对象,他们身上穿的衣服就可以叫做实例变量。 如果
// 一个类中有静态变量的话,程序首先会把该静态变量加载进内存中,也就是在堆中开辟一个区域专门
// 存放。以后不管你new多少个类的对象,该静态变量永远都是在那里的。也就是说,静态变量在类的初始
// 化一次后,系统就不会为该变量开辟新的内存空间。而每new一个类的对象,系统就会重新在 堆内存中
// 开辟一个新空间来存放该类的实例对象,并且栈中也会有一个新的引用变量去指向它。 静态方法也是类
// 似,但是有一点要强调,静态方法只中不能调用非静态方法。因为被static修饰的方法会首先被Classlo
// ader对象先加载进内存,而这个时候可能其它的非静态方法或者变量还没有被加载进来。就好比我现在想
// 做包子,现在面粉被static修饰,首先已经拿到你身边,可是因为包子馅不是static修饰的,所以可能包
// 子馅儿还没运过来,你说怎么做的出包子呢。 被static修饰过的都是随着类的初始化后就产生了,在堆
// 内存中都有一块专门的区域来存放,所以只需要类名点方法名或者变量名即可。而非静态的就必须通过类
// 的对象去调相应的。就像是你想要红色的衣服,你必须是从穿红色的衣服的人的身上拿过来才行,所以
// 你必须找到穿红色衣服的人,也就是类的实例对象,而你如果要去找一个桌子,而桌子就在房间里摆着
// ,你只要进到房间里直接走过去拿来就可以了~~



********传入参数*********
从java代码中把数据传入到mapper文件的sql语句中。
1)parameterType:写在mapper文件中的UI个属性,表示dao接口中的参数的数据类型
  parameterType 它的值是java的数据类型全限定名称或者是mybatis定义的别名。
例如:parameterType="java.lang.Integer"
parameterType="int"
注意:parameterType不是强制的,mybatis通过反射机制能够发现接口参数的数据类型,可以不写

Dao 接口中方法的参数只有一个简单类型(java 基本类型和 String),占位符 #{ 任意字符 },和方

法的参数名无关

使用#{}之后,mybatis是使用jdbc中的PerparedStatemnt对象
由mybatis执行下面的代码:
1.mybatis创建Connection ,perparedstatement对象
String sql=seledt*from student where id={studentid};
perparedStatement pst=conn.perparedStatemnt(sql);
pst.setint(1,1001);
2.执行sql封装为resultTyepe="com.anyu.domain.Student"这个对象
Result rs=ps.excuteQuery();
Student student=new student();
while(rs.next()){

student.setId(rs.getInt(“id”);
student.setName(rs.getString(“name”);
student.setemail(rs.geString(“email”);
student.setAge(rs.getInt(“age”);
}
return student

3)多个参数,使用@param命名参数
接口 public List selectMulitParam(@Param(“myname”)String name,@Param(“myage”)Integer age)
使用@Param(“参数名”)String name

mapper 文件 select * from student where name = #{myname} or age=#{myage}

4)多个参数-使用对象
使用 java 对象传递参数, java 的属性值就是 sql 需要的参数值。 每一个属性就是一个参数。
语法格式: #{ property,javaType=java 中数据类型名,jdbcType=数据类型名称 }
javaType, jdbcType 的类型 MyBatis 可以检测出来,一般不需要设置。常用格式 #{ property }
创建保存参数值的对象 QueryParam
package com.bjpowernode.vo;
public class QueryParam {
private String queryName;
private int queryAge;
//set ,get 方法
}
接口方法:
List selectMultiObject(QueryParam queryParam);
mapper 文件:

select id,name,email,age from student where name=#{queryName} or age
=#{queryAge}

select id,name,email,age from student
where name=#{queryName,javaType=string,jdbcType=VARCHAR}
or age =#{queryAge,javaType=int,jdbcType=INTEGER}

5)多个参数-按位置
参数位置从 0 开始, 引用参数语法 #{ arg 位置 } , 第一个参数是#{arg0}, 第二个是#{arg1}
注意:mybatis-3.3 版本和之前的版本使用#{0},#{1}方式, 从 mybatis3.4 开始使用#{arg0}方式。
接口方法:
List selectByNameAndAge(String name,int age);
mapper 文件

select id,name,email,age from student where name=#{arg0} or age =#{arg1}

测试方法:
@Test
public void testSelectByNameAndAge(){
//按位置参数
List stuList = studentDao.selectByNameAndAge(“李力”,20);
stuList.forEach( stu -> System.out.println(stu));
}

6)Map 集合可以存储多个值,使用Map向 mapper 文件一次传入多个参数。Map 集合使用 String的 key,
Object 类型的值存储参数。 mapper 文件使用 # { key } 引用参数值。
例如:Map<String,Object> data = new HashMap<String,Object>();
data.put(“myname”,”李力”);
data.put(“myage”,20);
接口方法:
List selectMultiMap(Map<String,Object> map);
mapper 文件:

select id,name,email,age from student where name=#{myname} or age =#{myage}

#:占位符,告诉 mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替
sql 语句的“?”。这样做更安全,更迅速,通常也是首选做法,
mapper 文件

select id,name,email,age from student where id=#{studentId}

转为 MyBatis 的执行是:
String sql=” select id,name,email,age from student where id=?”;
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,1005);
解释:
where id=? 就是 where id=#{studentId} ps.setInt(1,1005) , 1005 会替换掉 #{studentId}
$ 字符串替换,告诉 mybatis 使用 包含的“字符串”替换所在位置。使用 S t a t e m e n t 把 s q l 语句和 包含的“字符串”替换所在位置。使用 Statement 把 sql 语句和 包含的字符串替换所在位置。使用Statementsql语句和{}的
内容连接起来。主要用在替换表名,列名,不同列排序等操作。

对象执行是Statement执行效率低,这种方式是连接字符串,存在安全隐患。

1.使用${myname}
propertils:
myname=zhangsan
age=19

2.xml中扫描:

<context:property-placeholder location="classpath:bao1/propertils-test"/>
3.
    @Value("${myname}")
private  String name;


IOC能实现解耦合-loc能够实现业务对象之间的解耦合,例如service和dao对象之间的解耦合。


*********AOP,面向切面编程*********
JDK动态代理
CGLIB动态代理
不使用AOP的开发方式

修饰符有public、protected、private,当然还有缺省的(default)修饰符
,缺省的就是方法名前无任何修饰符。

缺省的(也就是你认为的默认修饰符)修饰符的访问权限都不同于public、
protected、private所修饰的方法。所以访问权限其实有四种。

获取主键自增的值

select @@identity

____------动态sql------

if标签

select * from flower where 1=1
<if test[=“param1!=null and param1!=‘’”>
and name=#{param1}


and production=#{param2}


where 标签
自动添加where标签关键字,自动去掉and关键字

select * from flower where 1=1

<choose标签》
相当于if()if()elseif()。。。else(),只取一个成立条件
select id=“selectMore” resultType=“flower”>
select * from flower where 1=1


<when test[=“param1!=null and param1!=‘’”>
name=#{param1}


and production=#{param2}


1=1



set标签
只能用于修改,会自动添加set关键字,会自动去掉最后一个逗号

update flower


name=#{name},


production=#{production}


where id=#{id}

标签
四个属性
prefix增加前缀
perfixoverrides去除前缀
suffix增加后缀
suffixoverrides去掉后缀

update flower


name=#{name},


production=#{production}


where id=#{id}

标签 collection 跟参数类型,不是变量名称,对应还有Array
进行一个循环操作

delete from flower where id in

#{i}

标签,标定标签

用bind绑定value的值
name like#{pa}

sql标签:抽离公共的代码,避免使用*,*虽然使用方便,但是执行效率低

id,name,price,production

使用时只需要引入即可
即:

当数据库中与实体类名称不一时:
两种解决方案,1在查询时使用as取一个别名,数据库在查询的时候是根据最终结果查询的。
2:将自动映射改为手动映射

在mapper.xml文件中
使用标签

这是根据主键修改
这是修改列名

在查询结果的时候使用

N+1联表查询

select * from student

<resutlMap id="rm2,type="student>



可省略
过程:select * from student的时候
通过association关联另外一条sql
select * from clazz where cid=?
?是通过
select * from student 后查询到的cid去查询的 返回一个clazz类型保存包clazz字段中

第二种方式:先查出班级cid,然后根据cid去查询学生列表
<select id=“selectOne” resultMap"rm2">
select * from clazz



select * form student where cid=#{param1}

先查询班级信息,然后根据班级cid去查询学生的列表,最后得出所有学生的信息
流程:查询所有班级信息,根据resultMap去查询resultMap标签的内容
result column=“cid” 将查出来的cid去赋值给学生的查询语句
collection是查多条记录是集合,association查一条是对象
otType指的是泛型
返回的resultMap是type="clazz"类型

懒加载的实现:

不管用不用都把数据查出来叫做积极加载
延迟加载,又称按需加载,延迟加载的内容等到真正使用时才进行加载(查询),多用在关联对象或集合中。
延迟加载的好处:先从单标查询,需要时再从关联表去关联查询,大大降低数据库在单位时间内的查询工作量,将工作在时间上的分配更
加均匀,而且单表要比关联查询多张表速度更快。

配置:第一步:在全局开关:
在mybatis.xml中打开延迟加载的开关,配置完成后所有的association和collection元素都生效



lazyLodaingEnabled:是否开启延迟加载,是mybatis是否启用懒加载的全局开关。
当开启时,所有关联对象都会延迟加载,特定关联关系中可通过设置fetchType属性来覆盖该项的开关。
aggressiveLazyLoading:当开启时,然和方法的调用都会懒加载对象的所有属性。
否则每个属性会按需加载。
第二步:分开关:指定的association和colleaction元素中配置fetchType属性,
eager:表示立刻加载;lazy表示延迟加载,将覆盖全局延迟配置。
当我们不需要所有属性都懒加载的时候
aggressiveLazyLoading配置成false,然后去给指定的association和colleaction元素中配置fetchType

优点:延迟在家可以根据用户的需要动态的决定查询数据的时机,可以将查询的工作量在时间上分散,减少单位时间对于数据库的查询次数,进而减少了数据库单位时间
内的运算压力,提高了数据库的反应数据,级联查询将一个多表、关联查询转换成多个单边查询,sql语句
变得简单,单次单表查询比单次表查询效率更高,相应速度更快。

多表查询,执行一条sql语句,但是要将所有的字段写出来

*8缓存
缓存是一种临时存储少量数据至内存或者二磁盘的一种技术,减少数据的加载此时,可以降低工作量,提高程序响应速度。
mybatis的缓存将相同条件的sql语句执行一遍后,所得到的结果存在内存或者某种缓存介质中,当下次遇到一一模一样
的查询sql时候不再与数据库交互,而是从缓存中获得结果,减少服务器压力。
mybatis允许使用缓存。
缓存一般设置在高度读/写的存储器上,比如服务器的内存,能够有效的提供系统性能,Mybatis
分为一级缓存和二级缓存,同时也配置关于缓存的设置。
一级存储是SqlSession上的缓存,二级缓存是在SqlSessionFactory(namespace)上的缓存,默认情况下,MyBatis
开启一级缓存,没有开启二级缓存。
当数据量较大的时候可以借助第三方缓存环境,或者redis缓存来协助保存Mybatis 的二级缓存数。

一级缓存在sqlsession中,当不同用户时,缓存就失效了,开启二级缓存
在mapper中配置标签默认开启全局配置。

二级缓存未必完全使用内存,有可能占用磁盘存储,缓存中存储的javaBean对象必须实现序列化接口
implements Serializable
经过设置后,第一个SelSession会首先去二级缓存中查找,如果不存在,就查询数据库,在
commit()或者close()的时候将数据放入到二级缓存,第二个SqlSession执行相同sql语句查询时就直接从二级缓存中获取了。
注意:1)myBatis的二级缓存的缓存介质有多种多样,而并不一定是在内存中,所以需要对javaBean对象实现序列化接口。
2)二级缓存是以namespace为单位的,不同的namespace下的操作互不影响
3)查询数据顺序 二级–》一级–》数据库–》把数据保存到一级,当sqlsession关闭或者提交的时候,把数据刷入到二级缓存中。
4)加入Cache元素后,会对响应命名空间的所有select元素查询结果进行缓存,
二位其中的insert,update,delete在操作是会清空整个namespace的缓存。
5)cache有一些可选的属性,type,eviction,flushInterval,size、,readOnly,blocking

当一个类实现了Seializable接口(该接口仅为标记接口,不包含任何方法定义),表示该类可以序列化,序列化的目的是将一个实现了Serializable接口的对象可以转换成一个字节序列,保存对象的状态。
把该字节序列保存起来(例如:保存在一个文件里),以后可以随时将该字节序列恢复为原来的对象。甚至可以将该字节序列放到其他计算机上或者通过网络传输到其他计算机上恢复,只有该计算机平台存在相应的类就可以正常恢复为原来的对象。
一个对象实现Serializable接口序列化,先要创建某些OutputStream对象,然后将其封装在一个ObjectOutputStream对象内,再调用writeObject()方法,即可序列化一个对象,反序列化,InputStream,再调用readObject()方法。(writeObject和readObject本身就是线程安全的,传输过程中是不允许被并发访问的,所以对象只能一个一个接连不断的传过来)。
如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,transient代表对象的临时数据, static对象变量在反序列化时取得的值为当前jvm中对应类中对应static变量的值,而transient(瞬态)关键字则一般用于标识那些在序列化时不需要传递的状态变量。
6)如果在加入Cache元素的前提下让个别select元素不使用缓存,可以使用useCache属性,
设置为false,useCache控制当前sql语句是否启用缓存, flushCache控制当前sql执行一次后是否刷新缓存

mysql函数:
LENGTH(str):获取长度

select LENGTH(‘abc123’);

查询结果:6

select LENGTH(‘中公’);

查询结果:6

CHAR_LENGTH(str):获取字符数

select CHAR_LENGTH(‘abc123’);

查询结果:6

select CHAR_LENGTH(‘中公’);

查询结果:2

SUBSTRING(str,pos,len):字符串截取

select SUBSTRING(‘13500260707’,4,2);

注意:pos从1开始,且包含,len:截取长度。

查询结果:00

select SUBSTRING(‘13500260707’,4);

注意:不传len,截取到最后。

查询结果:00260707

select SUBSTRING(‘13500260707’,4,20);

注意:超过总长度,也是截取到最后。

查询结果:00260707

REPLACE(str,from_str,to_str):字符串替换

select REPLACE(‘zhonggong123ujiuye’,‘123’,‘’);

查询结果:zhonggongujiuye

select REPLACE(‘abc123nmabc’,‘abc’,‘QQ’);

查询结果:QQ123nmQQ

REVERSE(str):字符串反转

select REVERSE(‘i love you’) ;

查询结果:uoy evol i

INSERT(s1,pos,len,s2):插入指定位置并替换

select INSERT(‘13211223344’,4,4,‘****’);

注意:pos从1开始,且包含,len:截取长度。

查询结果:132****3344

RAND() :返回 0 到 1 的随机数

select RAND();

查询结果:

0.7349283659283746

RAND(x) :

返回 0 到 1 的随机数,其中x的取值为1-65535,如每次x的取值相同,则返回的随机数也相同

select RAND(7);

查询结果:

0.7439285923573926

select RAND(7);

查询结果:

0.7439285923573926

使用rand()生成一个m-n之间的随机数

Select floor(rand()*(n-m+1)+m)

TRIM([remstr FROM] str) :

去除两端指定字符串或空格。

去除两端空格:

select TRIM(’ ujiuye ujiuye ');

查询结果:ujiuye ujiuye

去除两端指定字符串:

select TRIM(‘ujiuye’ from ‘ujiuyeujiuye123123ujiuye’);

查询结果:123123

LTRIM(str)/RTRIM(str):

去除左边/右边空格

去除左边空格:

select LTRIM(’ A A ');

查询结果:A A (后面还有空格)

去除右边空格:

select RTRIM(’ A A ');

结果: A A

MOD(x,y)

返回 x 除以 y 以后的余数

SELECT MOD(10,3);

查询结果:

另外一种写法:

SELECT 10%3;

查询结果

图片
IF(expr,v1,v2)

如果表达式 expr 成立,返回结果 v1;否则,返回结果 v2

SELECT IF(11 < 2,‘正确’,‘错误’);

查询结果:错误

SELECT IF(11 > 2,‘正确’,‘错误’);

查询结果:正确

图片
图片
IFNULL(v1,v2)

如果 v1 的值不为 NULL,则返回 v1,否则返回 v2。

SELECT IFNULL(null,‘空’);

查询结果:空

SELECT IFNULL(“我和我亲爱的祖国”,‘空’);

查询结果:我和我亲爱的祖国

图片
图片
ISNULL(expression)

判断表达式是否为 NULL

SELECT ISNULL(1);

查询结果:0

SELECT ISNULL(null);

查询结果:1

图片
图片
时间函数

#获取当前时间

select CURRENT_TIMESTAMP();

查询结果:2020-07-14 16:54:54

#格式化日期 年月日

select DATE_FORMAT(‘2020/10/01’,‘%Y-%m-%d %H:%i:%s’);

查询结果:2020-10-01 00:00:00

#取出 年月日

select YEAR(CURRENT_TIMESTAMP());

查询结果:2020

select MONTH(CURRENT_TIMESTAMP());

查询结果:10

select DAY(CURRENT_TIMESTAMP());

查询结果:01

#日期加一天,一月,一年

当前时间:2020-10-01 15:20:17

SELECT ADDDATE(CURRENT_TIMESTAMP(),INTERVAL 1 DAY);

查询结果:2020-10-01 15:20:17

SELECT ADDDATE(CURRENT_TIMESTAMP(),INTERVAL 1 MONTH);

查询结果:2020-11-01 15:20:17

SELECT ADDDATE(CURRENT_TIMESTAMP(),INTERVAL 1 YEAR);

查询结果:2021-10-01 15:20:17

#日期减一天,一月,一年

SELECT ADDDATE(CURRENT_TIMESTAMP(),INTERVAL -1 DAY);

查询结果:2020-10-01 15:20:17

SELECT ADDDATE(CURRENT_TIMESTAMP(),INTERVAL -1 MONTH);

查询结果:2020-09-01 15:20:17

SELECT ADDDATE(CURRENT_TIMESTAMP(),INTERVAL -1 YEAR);

查询结果:2019-10-01 15:20:17

#日期比较

SELECT CURRENT_TIMESTAMP() > ADDDATE(CURRENT_TIMESTAMP(),INTERVAL 1 day);

查询结果:0

SELECT CURRENT_TIMESTAMP() > ADDDATE(CURRENT_TIMESTAMP(),INTERVAL -1 day);

简述Mybatis的插件运行原理,以及如何编写一个插件。
Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、
Executor这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现
接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是
InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。
实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一
个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。
parameterHandler,我们传入的数据类型是java类型的,转换到数据库执行的类型,这个就是一个转换工具。
ResultSetHandler就是结果集,将数据库返回的结果封装为java对象。
statementHandler负责设置参数,负责将结果集进行转换。
executor 调度的核心执行器,负责生成sql,管理缓存。
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
setProperties 方法是在 MyBatis 进行配置插件的时候可以配置自定义相关属性,即:接口实现对象的
参数配置;
plugin 方法是插件用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的
代理,可以决定是否要进行拦截进而决定要返回一个什么样的目标对象,官方提供了示例:return
Plugin. wrap(target, this);
intercept 方法就是要进行拦截的时候要执行的方法。
自定义插件实现示例
官方插件实现:
@Intercepts({@Signature(type = Executor. class, method = “query”,
args = {MappedStatement. class, Object. class, RowBounds. class, ResultHandler. class})})
public class TestInterceptor implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
Object target = invocation. getTarget(); //被代理对象
Method method = invocation. getMethod(); //代理方法
Object[] args = invocation. getArgs(); //方法参数
// do something . . . . . . 方法拦截前执行代码块
Object result = invocation. proceed();
// do something . . . . . . . 方法拦截后执行代码块
return result;
}
public Object plugin(Object target) {
return Plugin. wrap(target, this);
}}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值