mysql查询数据库第⼀条记录_SQL获取第⼀条记录的⽅法
(sqlserver、oracl。。。
初识 MyBatis MyBatis 是第⼀个⽀持⾃定义 SQL、存储过程和⾼级映射的类持久框架。MyBatis 消除了⼤部分 JDBC 的样板代码、⼿动设置参数以及检索结果。MyBatis 能够⽀持简单的 XML 和注解配置规则。使 Map 接⼝和 POJO 类映射到数据库字段和记录。
MyBatis 的特点 那么 MyBatis 具有什么特点呢?或许我们可以从如下⼏个⽅⾯来描述
MyBatis 中的 SQL 语句和主要业务代码分离,我们⼀般会把 MyBatis 中的 SQL 语句统⼀放在 XML 配置⽂件中,便于统⼀维护。
解除 SQL 与程序代码的耦合,通过提供 DAO 层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。SQL 和代码的分离,提⾼了可维护性。
MyBatis ⽐较简单和轻量
本⾝就很⼩且简单。没有任何第三⽅依赖,只要通过配置 jar 包,或者如果你使⽤ Maven 项⽬的话只需要配置 Maven 以来就可以。易于使⽤,通过⽂档和源代码,可以⽐较完全的掌握它的设计思路和实现。
屏蔽样板代码 MyBatis 回屏蔽原始的 JDBC 样板代码,让你把更多的精⼒专注于 SQL 的书写和属性-字段映射上。
编写原⽣ SQL,⽀持多表关联
MyBatis 最主要的特点就是你可以⼿动编写 SQL 语句,能够⽀持多表关联查询。
提供映射标签,⽀持对象与数据库的 ORM 字段关系映射
ORM 是什么?对象关系映射(Object Relational Mapping,简称ORM) ,是通过使⽤描述对象和数据库之间映射的元数据,将⾯向对象语⾔程序中的对象⾃动持久化到关系数据库中。本质上就是将数据从⼀种形式转换到另外⼀种形式。
提供 XML 标签,⽀持编写动态 SQL。
你可以使⽤ MyBatis XML 标签,起到 SQL 模版的效果,减少繁杂的 SQL 语句,便于维护。
MyBatis 整体架构
MyBatis 最上⾯是接⼝层,接⼝层就是开发⼈员在 Mapper 或者是 Dao 接⼝中的接⼝定义,是查询、
新增、更新还是删除操作;中间层是数据处理层,主要是配置 Mapper -> XML 层级之间的参数映射,SQL 解析,SQL 执⾏,结果映射的过程。上述两种流程都由基础⽀持层来提供功能⽀撑,基础⽀持层包括连接管理,事务管理,配置加载,缓存处理等。
接⼝层
在不与Spring 集成的情况下,使⽤ MyBatis 执⾏数据库的操作主要如下:
InputStream is = ResourceAsStream("l");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
sqlSession = factory.openSession();
其中的SqlSessionFactory,SqlSession是 MyBatis 接⼝的核⼼类,尤其是 SqlSession,这个接⼝是MyBatis 中最重要的接⼝,这个接⼝能够让你执⾏命令,获取映射,管理事务。
数据处理层
配置解析 在 Mybatis 初始化过程中,会加载 l 配置⽂件、映射配置⽂件以及 Mapper 接⼝中的注解信息,解析后的配置信息会形成相应的对象并保存到 Configration 对象中。之后,根据该对象创建SqlSessionFactory 对象。待 Mybatis 初始化完成后,可以通过 SqlSessionFactory 创建 SqlSession 对象并开始数据库操作。 SQL 解析与 scripting 模块 Mybatis 实现的动态 SQL 语句,⼏乎可以编写出所有满⾜需要的 SQL。
Mybatis 中 scripting 模块会根据⽤户传⼊的参数,解析映射⽂件中定义的动态 SQL 节点,形成数据库能执⾏的SQL 语句。
SQL 执⾏ SQL 语句的执⾏涉及多个组件,包括 MyBatis 的四⼤核⼼,它们是: Executor、StatementHandler、ParameterHandler、ResultSetHandler。SQL 的执⾏过程可以⽤下⾯这幅图来表⽰
MyBatis 层级结构各个组件的介绍(这⾥只是简单介绍,具体介绍在后⾯):
SqlSession: ,它是 MyBatis 核⼼ API,主要⽤来执⾏命令,获取映射,管理事务。接收开发⼈员提供 Statement Id 和参数。并返回操作结果。Executor :执⾏器,是 MyBatis 调度的核⼼,负责 SQL 语句的⽣成以及查询缓存的维护。StatementHandler : 封装了JDBC Statement 操作,负责对 JDBC Statement 的操作,如设置参数、将Statement 结果集转换成 List 集合。ParameterHandler : 负责对
⽤户传递的参数转换成 JDBC Statement 所需要的参数。ResultSetHandler : 负责将 JDBC 返回的 ResultSet 结果集对象转换成 List
类型的集合。TypeHandler : ⽤于 Java 类型和 JDBC 类型之间的转换。MappedStatement : 动态 SQL 的封装SqlSource : 表⽰从XML ⽂件或注释读取的映射语句的内容,它创建将从⽤户接收的输⼊参数传递给数据库的 SQL。Configuration: MyBatis 所有的配置信息都维持在 Configuration 对象之中。
基础⽀持层
反射模块 Mybatis 中的反射模块,对 Java 反射进⾏了很好的封装,提供了简易的 API,⽅便上层调⽤,并且对反射操作进⾏了⼀系列的优化,⽐如,缓存了类的 元数据(MetaClass)和对象的元数据(MetaObject),提⾼了反射操作的性能。 类型转换模块
Mybatis 的别名机制,能够简化配置⽂件,该机制是类型转换模块的主要功能之⼀。类型转换模块的另⼀个功能是实现 JDBC 类型与 Java 类型的转换。在 SQL 语句绑定参数时,会将数据由 Java 类型转换成 JDBC 类型;在映射结果集时,会将数据由 JDBC 类型转换成 Java 类型。
⽇志模块
在 Java 中,有很多优秀的⽇志框架,如 Log4j、Log4j2、slf4j 等。Mybatis 除了提供了详细的⽇志输
出信息,还能够集成多种⽇志框架,其⽇志模块的主要功能就是集成第三⽅⽇志框架。
资源加载模块
该模块主要封装了类加载器,确定了类加载器的使⽤顺序,并提供了加载类⽂件和其它资源⽂件的功能。
解析器模块
该模块有两个主要功能:⼀个是封装了 XPath,为 Mybatis 初始化时解析 l配置⽂件以及映射配置⽂件提供⽀持;另⼀个为处理动态 SQL 语句中的占位符提供⽀持。mysql语句的执行顺序
数据源模块
Mybatis ⾃⾝提供了相应的数据源实现,也提供了与第三⽅数据源集成的接⼝。数据源是开发中的常⽤组件之⼀,很多开源的数据源都提供了丰富的功能,如连接池、检测连接状态等,选择性能优秀的数据源组件,对于提供ORM 框架以及整个应⽤的性能都是⾮常重要的。
事务管理模块
⼀般地,Mybatis 与 Spring 框架集成,由 Spring 框架管理事务。但 Mybatis ⾃⾝对数据库事务进⾏了抽象,提供了相应的事务接⼝和简单实现。
缓存模块
Mybatis 中有⼀级缓存和⼆级缓存,这两级缓存都依赖于缓存模块中的实现。但是需要注意,这两级缓存与Mybatis 以及整个应⽤是运⾏在同⼀个 JVM 中的,共享同⼀块内存,如果这两级缓存中的数据量较⼤,则可能影响系统中其它功能,所以需要缓存⼤量数据时,优先考虑使⽤ Redis、Memcache 等缓存产品。
Binding 模块
在调⽤ SqlSession 相应⽅法执⾏数据库操作时,需要制定映射⽂件中定义的 SQL 节点,如果 SQL 中出现了拼写错误,那就只能在运⾏时才能发现。为了能尽早发现这种错误,Mybatis 通过 Binding 模块将⽤户⾃定义的Mapper 接⼝与映射⽂件关联起来,系统可以通过调⽤⾃定义 Mapper 接⼝中的⽅法执⾏相应的 SQL 语句完成数据库操作,从⽽避免上述问题。注意,在开发中,我们只是创建了 Mapper 接⼝,⽽并没有编写实现类,这是因为 Mybatis ⾃动为 Mapper 接⼝创建了动态代理对象。
MyBatis 核⼼组件
在认识了 MyBatis 并了解其基础架构之后,下⾯我们来看⼀下 MyBatis 的核⼼组件,就是这些组件实现了从 SQL 语句到映射到 JDBC 再到数据库字段之间的转换,执⾏ SQL 语句并输出结果集。⾸先来认识 MyBatis 的第⼀个核⼼组件
SqlSessionFactory
对于任何框架⽽⾔,在使⽤该框架之前都要经历过⼀系列的初始化流程,MyBatis 也不例外。MyBatis 的初始化流程如下
joinfitString resource = "org/mybatis/l";
InputStream inputStream = ResourceAsStream(resource);
火焰龙卷风SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSessionFactory.openSession();
上述流程中⽐较重要的⼀个对象就是SqlSessionFactory,SqlSessionFactory 是 MyBatis 框架中的⼀个接⼝,它主要负责的是MyBatis 框架初始化操作 为开发⼈员提供SqlSession 对象
SqlSessionFactory 有两个实现类,⼀个是 SqlSessionManager 类,⼀个是 DefaultSqlSessionFactory 类
DefaultSqlSessionFactory : SqlSessionFactory 的默认实现类,是真正⽣产会话的⼯⼚类,这个类的实例的⽣命周期是全局的,它只会在⾸次调⽤时⽣成⼀个实例(单例模式),就⼀直存在直到服务器关闭。
SqlSessionManager : 已被废弃,原因⼤概是: SqlSessionManager 中需要维护⼀个⾃⼰的线程池,⽽使⽤MyBatis 更多的是要与Spring 进⾏集成,并不会单独使⽤,所以维护⾃⼰的 ThreadLocal 并没有什么意义,所以 SqlSessionManager 已经不再使⽤。
####SqlSessionFactory 的执⾏流程
下⾯来对 SqlSessionFactory 的执⾏流程来做⼀个分析
⾸先第⼀步是 SqlSessionFactory 的创建
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 1 从这⾏代码⼊⼿,⾸先创建了⼀个 SqlSessionFactoryBuilder ⼯⼚,这是⼀个建造者模式的设计思想,由 builder 建造者来创建 SqlSessionFactory ⼯⼚
然后调⽤ SqlSessionFactoryBuilder 中的 build ⽅法传递⼀个InputStream 输⼊流,Inputstream 输⼊流中就是你传过来的配置⽂件l,SqlSessionFactoryBuilder 根据传⼊的 InputStream 输⼊流和environment、properties属性创建⼀个XMLConfigBuilder对象。SqlSessionFactoryBuilder 对象调⽤XMLConfigBuilder 的parse()⽅法,流程如下。
XMLConfigBuilder 会解析/configuration标签,configuration 是 MyBatis 中最重要的⼀个标签,下⾯流程会介绍 Configuration 标签。
在 parseConfiguration ⽅法中,会对各个在 /configuration 中的标签进⾏解析
重要配置
说⼀下这些标签都是什么意思吧
properties,外部属性,这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性⽂件中配置,亦可通过 properties 元素的⼦元素来传递。
⼀般⽤来给 environment 标签中的 dataSource 赋值
还可以通过外部属性进⾏配置,但是我们这篇⽂章以原理为主,不会介绍太多应⽤层⾯的操作。
settings ,MyBatis 中极其重要的配置,它们会改变 MyBatis 的运⾏时⾏为。
php网站源码运行⼀般使⽤如下配置
typeAliases,类型别名,类型别名是为 Java 类型设置的⼀个名字。 它只和 XML 配置有关。
当这样配置时,Blog 可以⽤在任何使⽤ domain.blog.Blog 的地⽅。
typeHandlers,类型处理器,⽆论是 MyBatis 在预处理语句(PreparedStatement)中设置⼀个参数时,还是从结果集中取出⼀个值时,都会⽤类型处理器将获取的值以合适的⽅式转换成 Java 类型。
在 org.pe 包下有很多已经实现好的 TypeHandler,可以参考如下
你可以重写类型处理器或创建你⾃⼰的类型处理器来处理不⽀持的或⾮标准的类型。
具体做法为:实现 org.pe.TypeHandler 接⼝, 或继承⼀个很⽅便的类 org.pe.BaseTypeHandler,
然后可以选择性地将它映射到⼀个 JDBC 类型。
objectFactory,对象⼯⼚,MyBatis 每次创建结果对象的新实例时,它都会使⽤⼀个对象⼯⼚(ObjectF
actory)实例来完成。默认的对象⼯⼚需要做的仅仅是实例化⽬标类,要么通过默认构造⽅法,要么在参数映射存在的时候通过参数构造⽅法来实例化。如果想覆盖对象⼯⼚的默认⾏为,则可以通过创建⾃⼰的对象⼯⼚来实现。
public class ExampleObjectFactory extends DefaultObjectFactory { public Object create(Class type) { return
div是什么意思音乐术语constructorArgTypes, List
constructorArgs) { ate(type, constructorArgTypes, constructorArgs); } public void setProperties(Properties properties) { super.setProperties(properties); } public
boolean isCollection(Class
type) { return Collection.class.isAssignableFrom(type); } }
然后需要在 XML 中配置此对象⼯⼚
plugins,插件开发,插件开发是 MyBatis 设计⼈员给开发⼈员留给⾃⾏开发的接⼝,MyBatis 允许你在已映射语句执⾏过程中的某⼀点进⾏拦截调⽤。MyBatis 允许使⽤插件来拦截的⽅法调⽤包括:Executor、ParameterHandler、ResultSetHandler、StatementHandler 接⼝,这⼏个接⼝也是 MyBatis 中⾮常重要的接⼝,我们下⾯会详细介绍这⼏个接⼝。 environments,MyBatis 环境配置,MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应⽤于多种数据库之中。例如,开发、测试和⽣产环境需要有不同的配置;或者想在具有相同 Schema 的多个⽣产数据库中 使⽤相同的 SQL 映射。
这⾥注意⼀点,虽然 environments 可以指定多个环境,但是 SqlSessionFactory 只能有⼀个,为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
databaseIdProvider ,数据库⼚商标⽰,MyBatis 可以根据不同的数据库⼚商执⾏不同的语句,这种多⼚商的⽀持是基于映射语句中的databaseId 属性。
mappers,映射器,这是告诉 MyBatis 去哪⾥到这些 SQL 语句,mappers 映射配置有四种⽅式
上⾯的⼀个个属性都对应着⼀个解析⽅法,都是使⽤ XPath 把标签进⾏解析,解析完成后返回⼀个 DefaultSqlSessionFactory 对象,它是 SqlSessionFactory 的默认实现类。这就是 SqlSessionFactoryBuilder 的初始化流程,通过流程我们可以看到,初始化流程就是对⼀个个 /configuration 标签下⼦标签的解析过程。
SqlSession
在 MyBatis 初始化流程结束,也就是 SqlSessionFactoryBuilder -> SqlSessionFactory 的获取流程后,我们就可以通过SqlSessionFactory 对象得到 SqlSession 然后执⾏ SQL 语句了。具体来看⼀下这个过程‘
在 SqlSessionFactory.openSession 过程中我们可以看到,会调⽤到 DefaultSqlSessionFactory 中的openSessionFromDataSource ⽅法,这个⽅法主要创建了两个与我们分析执⾏流程重要的对象,⼀个是 Executor 执⾏器对象,⼀个是SqlSession 对象。执⾏器我们下⾯会说,现在来说⼀下 SqlSession 对象
SqlSession 对象是 MyBatis 中最重要的⼀个对象,这个接⼝能够让你执⾏命令,获取映射,管理事务。SqlSession 中定义了⼀系列模版⽅法,让你能够执⾏简单的 CRUD 操作,也可以通过 getMapper 获取 Mapper 层,执⾏⾃定义 SQL 语句,因为 SqlSession 在执⾏SQL 语句之前是需要先
开启⼀个会话,涉及到事务操作,所以还会有 commit、 rollback、close 等⽅法。这也是模版设计模式的⼀种应⽤。
MapperProxy
MapperProxy 是 Mapper 映射 SQL 语句的关键对象,我们写的 Dao 层或者 Mapper 层都是通过 MapperProxy 来和对应的 SQL 语句进⾏绑定的。下⾯我们就来解释⼀下绑定过程
这就是 MyBatis 的核⼼绑定流程,我们可以看到 SqlSession ⾸先调⽤ getMapper ⽅法,我们刚才说到 SqlSession 是⼤哥级别的⼈物,只定义标准(有⼀句话是怎么说的来着,⼀流的企业做标准,⼆流的企业做品牌,三流的企业做产品)。
也就是说,MyBatis 中 Mapper 和 SQL 语句的绑定正是通过动态代理来完成的。
通过动态代理,我们就可以⽅便的在 Dao 层或者 Mapper 层定义接⼝,实现⾃定义的增删改查操作了。那么具体的执⾏过程是怎么样呢?上⾯只是绑定过程,别着急,下⾯就来探讨⼀下 SQL 语句的执⾏过程。
MapperProxyFactory 会⽣成代理对象,这个对象就是 MapperProxy,最终会调⽤到 ute ⽅法,execute ⽅法⽐较长,其实逻辑⽐较简单,就是判断是 插⼊、更新、
struts2搭建apache删除 还是 查询 语句,其中如果是查询的话,还会判断返回值的类型,我们可以点进去看⼀下都是怎么设计的。
很多代码其实可以忽略,只看我标出来的重点就好了,我们可以看到,不管你前⾯经过多少道关卡处理,最终都逃不过 SqlSession 这个⽼⼤制定的标准。
我们以 selectList 为例,来看⼀下下⾯的执⾏过程。 这是 DefaultSqlSession 中 selectList 的代码,我们可以看到出现了 executor,这是什么呢?我们下⾯来解释。
Executor
还记得我们之前的流程中提到了 Executor(执⾏器) 这个概念吗?我们来回顾⼀下它第⼀次出现的位置。
由 Configuration 对象创建了⼀个 Executor 对象,这个 Executor 是⼲嘛的呢?下⾯我们就来认识⼀下
Executor 的继承结构
每⼀个 SqlSession 都会拥有⼀个 Executor 对象,这个对象负责增删改查的具体操作,我们可以简单的将它理解为 JDBC 中 Statement 的封装版。 也可以理解为 SQL 的执⾏引擎,要⼲活总得有⼀个发起⼈吧,可以把 Executor 理解为发起⼈的⾓⾊。
⾸先先从 Executor 的继承体系来认识⼀下
如上图所⽰,位于继承体系最顶层的是 Executor 执⾏器,它有两个实现类,分别是BaseExecutor和 CachingExecutor。
BaseExecutor 是⼀个抽象类,这种通过抽象的实现接⼝的⽅式是适配器设计模式之接⼝适配 的体现,是Executor 的默认实现,实现了⼤部分 Executor 接⼝定义的功能,降低了接⼝实现的难度。BaseExecutor 的⼦类有三个,分别是 SimpleExecutor、ReuseExecutor 和BatchExecutor。
SimpleExecutor : 简单执⾏器,是 MyBatis 中默认使⽤的执⾏器,每执⾏⼀次 update 或 select,就开启⼀个Statement 对象,⽤完就直接关闭 Statement 对象(可以是 Statement 或者是 PreparedStatment 对象)
ReuseExecutor : 可重⽤执⾏器,这⾥的重⽤指的是重复使⽤ Statement,它会在内部使⽤⼀个 Map 把创建的Statement 都缓存起来,每次执⾏ SQL 命令的时候,都会去判断是否存在基于该 SQL 的 Statement 对象,如果存在 Statement 对象并且对应的 connection 还没有关闭的情况下就继续使⽤之前的 Statement 对象,并将其缓存起来。因为每⼀个 SqlSession 都有⼀个新的 Executor 对象,所以我们缓存在 ReuseExecutor 上的 Statement作⽤域是同⼀个 SqlSession。
BatchExecutor : 批处理执⾏器,⽤于将多个 SQL ⼀次性输出到数据库
CachingExecutor: 缓存执⾏器,先从缓存中查询结果,如果存在就返回之前的结果;如果不存在,再委托给Executor delegate 去数据库中取,delegate 可以是上⾯任何⼀个执⾏器。
Executor 的创建和选择 我们上⾯提到 Executor 是由 Configuration 创建的,Configuration 会根据执⾏器的类型创建,如下
这⼀步就是执⾏器的创建过程,根据传⼊的 ExecutorType 类型来判断是哪种执⾏器,如果不指定 ExecutorType ,默认创建的是简单执⾏器。它的赋值可以通过两个地⽅进⾏赋值:
可以通过
标签来设置当前⼯程中所有的 SqlSession 对象使⽤默认的 Executor
另外⼀种直接通过Java对⽅法赋值的⽅式
session = factory.openSession(ExecutorType.BATCH);
Executor 的具体执⾏过程
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论