基于Mybatis的配置文件入门必看篇

网友投稿 930 2022-12-28

基于Mybatis的配置文件入门必看篇

基于Mybatis的配置文件入门必看篇

Mybatis 配置文件入门

从这篇文章开始,我们将从其核心配置文件入手,对Mybatis支持的核心配置文件进行简单详细的描述。

从下面这段代码是我们在使用mybatis前的配置初始化过程

我们通过阅读其源码来逐步了解内部实现原理。

// Mybatis 通过SqlSessionFactory获取SqlSession, 然后才能通过SqlSession与数据库进行交互

private static SqlSessionFactory getSessionFactory() {

SqlSessionFactory sessionFactory = null;

String resource = "configuration.xml";

try {

sessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader(resource));

} catch (IOException e) {

e.printStackTrace();

}

return sessionFactory;

}

我们进入到SqlSessionFactoryBuilder类里面

查看其源码:

/**

* Copyright 2009-2016 the original author or authors.

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* http://apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package org.apache.ibatis.session;

import java.io.IOException;

import java.io.InputStream;

import java.io.Reader;

import java.util.Properties;

import org.apache.ibatis.builder.xml.XMLConfigBuilder;

import org.apache.ibatis.exceptions.ExceptionFactory;

import org.apache.ibatis.executor.ErrorContext;

import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;

/**

* Builds {@link SqlSession} instances.

*

* @author Clinton Begin

*/

public class SqlSessionFactoryBuilder {

public SqlSessionFactory build(Reader reader) {

return build(reader, null, null);

}

public SqlSessionFactory build(Reader reader, String environment) {

return build(reader, environment, null);

}

public SqlSessionFactory build(Reader reader, Properties properties) {

return build(reader, null, properties);

}

public SqlSessionFactory build(Reader reader, String environment, Properties properties) {

try {

XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);

return build(parser.parse());

} catch (Exception e) {

throw ExceptionFactory.wrapException("Error building SqlSession.", e);

} finally {

ErrorContext.instance().reset();

try {

reader.close();

} catch (IOException e) {

// Intentionally ignore. Prefer previous error.

}

}

}

public SqlSessionFactory build(InputStream inputStream) {

return build(inputStream, null, null);

}

public SqlSessionFactory build(InputStream inputStream, String environment) {

return build(inputStream, environment, null);

}

public SqlSessionFactory build(InputStream inputStream, Properties properties) {

return build(inputStream, null, properties);

}

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {

try {

XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);

return build(parser.parse());

} catch (Exception e) {

throw ExceptionFactory.wrapException("Error building SqlSession.", e);

} finally {

ErrorContext.instance().reset();

try {

inputStream.close();

} catch (IOException e) {

// Intentionally ignore. Prefer previous error.

}

}

}

public SqlSessionFactory build(Configuration config) {

return new DefaultSqlSessionFactory(config);

}

}

在这个类中,支持多种构造SqlSessionFactory的方法。可以只传入mybatis配置文件,也可以同时传入properties配置文件替代mybatis配置文件中的元素标签,另外也支持传入环境参数envirmont参数。

我们跟随着源码继续往下看:

public SqlSessionFactory build(Reader reader, String environment, Properties properties) {

try {

XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);

return build(parser.parse());

} catch (Exception e) {

throw ExceptionFactory.wrapException("Error building SqlSession.", e);

} finally {

ErrorContext.instance().reset();

try {

reader.close();

} catch (IOException e) {

// Intentionally ignore. Prefer previous error.

}

}

}

这里创建了一个XMLConfigBuilder类实例,通过他来对mybatis配置文件(一个xml配置文件)进行解析。

解析的代码入口如下所示:

public Configuration parse() {

if (parsed) {

throw new BuilderException("Each XMLConfigBuilder can only be used once.");

}

parsed = true;

parseConfiguration(parser.evalNode("/configuration"));

return configuration;

}

private void parseConfiguration(XNode root) {

try {

Properties settings = settingsAsPropertiess(root.evalNode("settings"));

//issue #117 read properties first

propertiesElement(root.evalNode("properties"));

loadCustomVfs(settings);

typeAliasesElement(root.evalNode("typeAliases"));

pluginElement(root.evalNode("plugins"));

objectFactoryElement(root.evalNode("objectFactory"));

objectWrappolOCterFactoryElement(root.evalNode("objectWrapperFactory"));

reflectorFactoryElement(root.evalNode("reflectorFactory"));

settingsElement(settings);

// read it after objectFactory and objectWrapperFactory issue #631

environmentsElement(root.evalNode("environments"));

databaseIdProviderElement(root.evalNode("databaseIdProvider"));

typeHandlerElement(root.evalNode("typeHandlers"));

mapperElement(root.evalNode("mappers"));

} catch (Exception e) {

throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);

}

}

从这里看出,配置文件是以configuration为根节点,在根节点之下有多个子节点,它们分别为:settings、properties、typeAliases、plugins、objectFactory、objectWrapperFactory、environments、databaseIdProvider、typeHandlers、mappers。

MyBatis核心配置文件标签简介

XML 映射配置文件

MyBatis的配置文件包含了影响MyBatis行为甚深的设置(settings)和属性(properties)信息。文档的顶层结果如下:

configuration配置

properties属性

setting设置

typeAliases类型命名

typeHandlers类型处理器

objectFactory对象工厂

plugins插件

environments环境

environment环境变量

transactionManager事务管理器

dataSource数据源

databaseIdProyider数据库厂商标识

mappers映射

properties

属性都是可外部配置且可动态替换的,既可以在典型的Java属性文件中配置,亦可通过properties元素的子元素来传递。

例如:

其中的属性就可以在整个配置文件中使用来替换需要动态配置的属性值。

比如:

properties属性:将数据库连接参数单独配置在jdbc.properties中,只需要在mybatis.xml文件中加载jdbc.properties的属性值。 在mybatis.xml中就不需要对数据库连接参数硬编码(硬编码是指将可变变量用一个固定值来代替的方法)。在properties 元素体内定义的属性首先被读取。然后会读取properties元素中resource或url加载属性,它会覆盖已读取的同名属性。

注意:如果在properties标签里面定义的属性被${}所引用了,对#{}不管用。那么它不会读取parameterType里面的参数值。比如properties里面定义了id属性,值为40,在映射文件中引用该值,${id}那么我从parameterType里面传值时,不管我传基本类型还是引用类型进去都不会覆盖这个${id}值。始终都会读取40.

属性也可以被传递到SqlSessionBuilder.build()方法中。

例如:

SqlSessionFactoryBuilder源码:

public SqlSessionFactory build(Reader reader, Properties properties) {

return build(reader, null, properties);

}

public SqlSessionFactory build(Reader reader, String environment, Properties properties) {

try {

XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);

return build(parser.parse());

} catch (Exception e) {

throw ExceptionFactory.wrapException("Error building SqlSession.", e);

} finally {

ErrorContext.instance().reset();

try {

reader.close();

} catch (IOException e) {

// Intentionally ignore. Prefer previous error.

}

}

}

typeAliases

类型别名是为Java类型设置一个短的名字。它只和XML配置有关,存在意义仅在于用来减少类完全限定名的冗余。

例如:

当这样配置时,Blog可以用在任何使用domain.blog.Blog的地方。

也可以指定一个包名,MyBatis会在包名下面搜索需要的Java Bean

比如:

每一个包domain.blog中的Java Bean,在没有注解的情况下,会使用Bean的首字母小写的非限定类名来作为它的别名。比如domain.blog.Author的别名为author;若有注解,则别名为其注解值。

看下面的例子:

@Alias("author") public class Author { ... }

mapper标签(映射配置):加载映射文件

Mapper XML文件

MyBatis的真正强大在于他的映射语句,也是它的魔力所在,由于它的异常强大,映射器的XML文件就显得相对简单。如果拿它跟具有相同功能的JDBC代码进行对比,你会立即发现省掉了将近95%的代码。MyBatis就是针对SQL构建的,并且比普通的方法做的更好。

mapper标签:映射文件的根节点,在根节点中支持九个元素。

namespace是用于绑定Dao接口的,当你的namespace绑定接口后,你可以不用写接口实现类,mybatis会通过该绑定自动帮你找到对应要执行的SQL语句

注意:接口中的方法与映射文件中的SQL语句的ID一一对应

SQL映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):

cache:给定命名空间的缓存配置

cache-ref:其命名空间缓存配置的引用。

resultMap:是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。

parameterMap:已废弃,老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除,这里不会记录。

sql:可被其他语句引用的可重用语句块。

insert:映射插入语句

update:映射更新语句

delete:映射更新语句

select:映射查询语句

select

查询语句是MyBatis中最常用的元素之一,光能把数据存到数据库中价值并不大,如果还能重新取出来才有用,多数应用也都是查询比修改要频繁。对每个插入、更新或删除操作,通常对应多个查询操作。这是MyBatis的基本原则之一,也是将焦点和努力放在查询和结果映射的原因。简单查询的select元素时非常简单的。

比如

这个语句被称作selectPerson,接收一个int(或Integer)类型的参数,并返回一个HashMap类型的对象,其中的键是列名,值便是结果行中的对应值。

注意参数符号:#{id}

select元素有很多属性允许你配置,来决定每条语句的作用细节。

SELECT多条件查询

parameterType用于传递参数多参数可以使用传入对象以及map的方式传递多个参数。

#{}表示传递的参数值 类同jdbc的? ${}表示直接将参数值替换类同'%值%'

比如:

SELECT * FROM PERSON WHERE ID = #{id} and name like ‘%${name}%'

Map中必须存在id和name的键值对

SELECT调用存储过程

创建存储过程prg_add(p1 in number,p2 in number,p3 out number)

Mybatis映射文件中使用select调用存储过程

{call pro_hello (

#{p1,mode=IN,jdbcType=NUMBER},

#{p2,mode=IN,jdbcType=NUMBER},

#{result,mode=OUT,jdbcType=NUMBER})}

]]>

测试调用过程

Map param = new HashMap();

param.put(“p1”, 1); param.put(“p2”, 2);

String returnValue = (String) session.selectOne(" prgAdd ", param);

System.out.println("result=" + param.get("result"));

System.out.println("returnValue=" + returnValue);

insert、update和delete

数据更变语句insert、update和delete的实现非常接近

insert、update和delete参数

parameterType:入参的全限定类名或类型别名

keyColumn:设置数据表自动生成的主键名。对特定数据库(如PostgreSQL),若自动生成的主键不是第一个字段则必须设置

keyProperty:默认值unset,用于设置getGeneratedKeys方法或selectKey子元素返回值将赋值到领域模型的哪个属性中

useGeneratedKey:取值范围true|false(默认值)设置是否使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。

mysql和SQLServer执行auto-generated key field,因此当数据库设置好自增长主键后,可通过JDBC的getGeneratedKeys方法获取。但像Oralce等不支持auto-generated key field的数据库就不能用这种方法获取主键了

flushCache:取值范围true(默认值)|false,设置执行该操作后是否会清空二级缓存和本地缓存

timeout:默认为unset(依赖jdbc驱动器的设置),设置执行该操作的最大时限,超时将抛异常

databaseId:取值范围oracle|mysql等,表示数据库厂家,元素内部可通过``来为特定数据库指定不同的sql语句

selectKey

对于不支持自动生成类型的数据库或可能不支持自动生成主键JDBC驱动来说,MyBatis有另外一种方法来生成主键。

这里有一个简单的示例,它可以生成一个随机ID(最好不要这么做,但这里展示了MyBatis处理问题的灵活性及其所关心的广度):

select FOOD_SEC.Nextval from dual

insert into food values(#{foodId},#{foodName},#{price})

在上面的示例中,selectKey元素将会首先运行,food的id会被设置,然后插入语句会被调用,这给了你一个和数据库中来处理自动生成的主键类似的行为,避免了使Java代码变得复杂

SQL

这个元素可以被用来定义可重用的SQL代码段,可以包含在其他语句中,它可以被静态地(在加载参数)参数化,不同的属性值太高包含的实例变化。

比如:

${alias}.id,${alias}.username,${alias}.password

这个SQL片段可以被包含在其他语句中,例如:

,

from some_table t1 cross join some_table t2

属性值可以用于包含的refid属性或者包含的字句里面的属性值。

Result Map

resultMap 元素时MyBatis中最重要最强大的元素。它就是让你远离90%的需要从结果集中取出数据的JDBC代码的那个东西,而且在一些情形下允许你做一些JDBC不支持的事情。事实上,编写相似于对复杂语句联合映射这些等同的代码,也许可以跨过上千行的代码。ResultMap的设计就是简单语句不需要明确的结果映射,而很多复杂语句确实需要描述它们的关系。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:小程序组件事件报错(小程序事件委托)
下一篇:智慧园区(智慧园区资产管理系统)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~