文章目录
MyBatis学习
前言:是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
环境:jdk1.8 mysql5.7 maven 3.6.1 IDEA
需要知识点:
- jdbc
- mysql
- java基础
- Maven
- Junit
安装Mybatis
方式一:
下载MyBatis的jar包,将 mybatis-x.x.x.jar文件置于类路径(classpath)中即可。
方式二:
使用 Maven 来构建项目,将下面的依赖代码置于 pom.xml 文件中
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
Maven引入MyBatis项目常用的依赖
mysql依赖、mybatis依赖、junit依赖
<dependencies>
<!--mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!--mysql驱动依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!--junit依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
Mybatis使用
-
引入相应jar包
在pom.xml中编写所需的jar包相应的标签
-
编写MyBatis核心配置文件
在resource文件中新建mybatis-config.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核心配置文件--> <configuration> <environments default="development"> <environment id="development"> <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="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>
注:一定别忘记写mapper标签,否则会报xml未注册错误,每一个mapper都需要在mybatis核心配置文件中注册
environments意味着可以配置多套环境,如
<!-- configuration核心配置文件-->
<configuration>
<!-- 默认环境为development 可以更改-->
<environments default="development">
<environment id="development">
<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="${password}"/>
</dataSource>
</environment>
<environment id="development2">
<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="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
-
编写mybatis工具类
package cmo.stu.utils; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; //目的:获取sqlSessionFactory,以便于获取sqlSession public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory ; static{ try{ String resource = "mybatis-config.xml"; //项目的mybatis配置文件的路径 InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); }catch(Exception e){} } public static SqlSession getSqlsession(){ // SqlSession sqlSession = sqlSessionFactory.openSession(); // return sqlSession; return sqlSessionFactory.openSession(); } }
4.实现类
package com.stu.pojo; public class Student { private int id ; private String name; public Student() { } public Student(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
4.dao接口
package com.stu.dao; import com.stu.pojo.Student; import java.util.List; //操作数据库对象的实体 public interface StuDao { List<Student> getStuList(); }
5.配置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="org.mybatis.example.BlogMapper"> <!-- id对应StuDao方法的名字--> <select id="getStuList" resultType="com.stu.dao.StuDao"> select * from student.students </select> </mapper>
6.测试
一、从 XML 中构建 SqlSessionFactory
Java文件中核心三行代码:
String resource = "org/mybatis/example/mybatis-config.xml"; //项目的mybatis配置文件的路径
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
xml文件:
包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)
简单罗列了最关键的部分:
<?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>
<environments default="development">
<environment id="development">
<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="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
二、从 SqlSessionFactory 中获取 SqlSession
SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。可通过 SqlSession 实例来直接执行已映射的 SQL 语句
方式一(推荐使用)
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
方式二(不推荐使用)
try (SqlSession session = sqlSessionFactory.openSession()) {
Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
}
方式比较:
代码不仅更清晰,更加类型安全,还不用担心可能出错的字符串字面值以及强制类型转换。
出现SqlSessionFactory为null情况
java.lang.NullPointerException
1.mybatis-config.xml环境搭配出现问题
如书写错误
2.导包出现问题
//正确
import org.apache.ibatis.io.Resources;
//错误
import javax.annotation.Resources
3.获取SqlSessionFactory的代码出现问题
如:重复定义SqlSessionFactory
4.target文件缺少配置文件
如缺少mybatis-config.xml,打开target目录仔细对比,缺少的复制回来
配置文件找不到情况
maven由于他的约定大于配置,我们之后可以能遇到我们写的配置文件,无法被导出或者生效的问题,
解决方案: 手动配置资源过滤
在build中配置resource,防止我们资源导出问题
<build>
<finalName>dubbo-provide</finalName>
<resources>
<resource>
<!--输出目录,默认为/target/classes-->
<targetPath>${project.build.outputDirectory}</targetPath>
<!-- 设定主资源目录 -->
<directory>src/main/java</directory>
<!-- 只处理如下配置中包含的资源类型 -->
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!-- 不处理如下配置中包含的资源类型(剔除下如下配置中包含的资源类型)-->
<excludes>
<exclude>**/*.yaml</exclude>
</excludes>
<!-- 是否对主资源目录开启资源过滤 -->
<filtering>true</filtering>
</resource>
<resource>
<!--输出目录,默认为/target/classes-->
<!-- <targetPath>${project.build.outputDirectory}</targetPath>-->
<!-- 设定主资源目录 -->
<directory>src/main/resources</directory>
<!-- 只处理如下配置中包含的资源类型 -->
<includes>
<include>*</include>
</includes>
<!-- 是否对主资源目录开启资源过滤 -->
<filtering>false</filtering>
</resource>
</resources>
</build>
由于我们maven的配置文件默认是在resource文件中,在mybatis中,我们的mapper配置文件在java目录中,运行时,target不会自动生成该配置文件而导致错误
因此,我们此问题也可用maven解决配置文件无法被导出或则生效(手动配置资源过滤)
在pom.xml中
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
实现增删查改
mapper传入参数选择
1.传入实体类:则该类的所有属性都可以当作参数
对象传递参数,直接在sq|中取对象的属性即可! [parameterType=“Object”]
只
2.基本类型:则可以省略该代码
只有一个基本类型参数的情况下,可以直接在sq|中取到!
3.Map传递参数,直接在sq|中取出key即可! [parameterType=“map”]
多个参数用Map,或者注解!
Map集合
当我们实体类的属性过多或者数据库的字段过多,但只需要查询条件为少量的字段,考虑使用
dao
Student getStuByMapId(Map<String ,Object> map);
mapper配置文件
<select id="getStuByMapId" parameterType="map" resultType="com.stu.pojo.Student">
select * from student.students where id=#{id}
</select>
测试
@Test
public void getStuByMapId(){
Map<String,Object> map = new HashMap<String,Object>();
map.put("id",1);
System.out.println(map);
SqlSession sqlsession = MybatisUtils.getSqlsession();
StuDao mapper = sqlsession.getMapper(StuDao.class);
Student student = mapper.getStuByMapId(map);
System.out.println(student);
sqlsession.close();
}
模糊查询怎么写?
- Java代码执行的时候,传递通配符% %
List<User> userList = mapper. getuserLike("%李%");
2.在sq|拼接中使用通配符!
select * from mybatis.user where name like "%"#{va1ue}
XMl配置
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
顺序不一致会报错误:
The content of element type” configuration" must match “(properties?,settings?,typeAliases?,typeHandlers?, objectFactory?, objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseldProvider?,mappers?)”. :5
属性(properties)
属性可以在外部进行配置(如:db.properties),并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置
如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:
- 首先读取在 properties 元素体内指定的属性。
- 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
- 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。.
-
通过方法参数传递的属性
<?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> <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/student?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/stu/dao/StuDao.xml"/> </mappers> </configuration>
-
配置外部文件,
?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="db.properties">
</properties>
<environments default="development">
<environment id="development">
<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="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/stu/dao/StuMapper.xml"/>
</mappers>
</configuration>
db.properties
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/student?useSSL=true&useUnicode=true&characterEncoding=UTF-8"
username = root
password = root
3.properties 元素体内指定的属性。
<?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="db.properties">
<property name="driver" value="driver"/>
<property name="url" value="url"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
</properties>
<environments default="development">
<environment id="development">
<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="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/stu/dao/StuMapper.xml"/>
</mappers>
</configuration>
db.properties为空
设置(setting)
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 | true | false | false |
aggressiveLazyLoading | 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods )。 | true | false | false (在 3.4.1 及之前的版本中默认为 true) |
multipleResultSetsEnabled | 是否允许单个语句返回多结果集(需要数据库驱动支持)。 | true | false | true |
useColumnLabel | 使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。 | true | false | true |
useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 | true | false | False |
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
autoMappingUnknownColumnBehavior | 指定发现自动映射目标未知列(或未知属性类型)的行为。NONE : 不做任何反应WARNING : 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARN )FAILING : 映射失败 (抛出 SqlSessionException ) | NONE, WARNING, FAILING | NONE |
defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置超时时间,它决定数据库驱动等待数据库响应的秒数。 | 任意正整数 | 未设置 (null) |
defaultFetchSize | 为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。 | 任意正整数 | 未设置 (null) |
defaultResultSetType | 指定语句默认的滚动策略。(新增于 3.5.2) | FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置) | 未设置 (null) |
safeRowBoundsEnabled | 是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 | true | false | False |
safeResultHandlerEnabled | 是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。 | true | false | True |
mapUnderscoreToCamelCase | 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 | true | false | False |
localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。 | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | 当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。 | OTHER |
lazyLoadTriggerMethods | 指定对象的哪些方法触发一次延迟加载。 | 用逗号分隔的方法列表。 | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定动态 SQL 生成使用的默认脚本语言。 | 一个类型别名或全限定类名。 | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
defaultEnumTypeHandler | 指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5) | 一个类型别名或全限定类名。 | org.apache.ibatis.type.EnumTypeHandler |
callSettersOnNulls | 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。 | true | false | false |
returnInstanceForEmptyRow | 当返回行的所有列都是空时,MyBatis默认返回 null 。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2) | true | false | false |
logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | 任何字符串 | 未设置 |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未设置 |
proxyFactory | 指定 Mybatis 创建可延迟加载对象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 以上) |
vfsImpl | 指定 VFS 的实现 | 自定义 VFS 的实现的类全限定名,以逗号分隔。 | 未设置 |
useActualParamName | 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1) | true | false | true |
configurationFactory | 指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3) | 一个类型别名或完全限定类名。 | 未设置 |
shrinkWhitespacesInSql | 从SQL中删除多余的空格字符。请注意,这也会影响SQL中的文字字符串。 (新增于 3.5.5) | true | false | false |
defaultSqlProviderType | Specifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the type (or value ) attribute on sql provider annotation(e.g. @SelectProvider ), when these attribute was omitted. | A type alias or fully qualified class name | Not set |
一个配置完整的 settings 元素的示例如下:
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
类型别名(typeAliases)
- 类型别名可为 Java 类型设置一个缩写名字。
- 仅用于 XML 配置,意在降低冗余的全限定类名书写。
方式一:
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
当这样配置时,Blog
可以用在任何使用 domain.blog.Blog
的地方。
方式二:可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
每一个在包 domain.blog
中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author
的别名为 author
。(若有注解,则别名为其注解值)
在实体类比较少的时候,使用第一种方式。
如果实体类十分多,建议使用第二种。
第一种可以DIY别名,第二种则不行,如果非要改,需要在实体上增加注解
@Alias("author")
public class Author {
...
}
下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。
_byte | byte |
---|---|
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
object | Object |
map | Map |
hashmap | HashMap |
list | List |
arraylist | ArrayList |
collection | Collection |
iterator | Iterator |
环境配置(environments)
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例,依此类推,记起来很简单:
- 每个数据库对应一个 SqlSessionFactory 实例
为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。可以接受环境配置的两个方法签名是:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
如果忽略了环境参数,那么将会加载默认环境,如下所示:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);
environments 元素定义了如何配置环境。
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
注意一些关键点:
- 默认使用的环境 ID(比如:default=“development”)。
- 每个 environment 元素定义的环境 ID(比如:id=“development”)。
- 事务管理器的配置(比如:type=“JDBC”)。
- 数据源的配置(比如:type=“POOLED”)。
默认环境和环境 ID 顾名思义。 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。
事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
- JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
- MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。例如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
映射器(mappers)
定义 SQL 映射语句。 首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:///
形式的 URL),或类名和包名等。例如:
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
这些配置会告诉 MyBatis 去哪里找映射文件,剩下的细节就应该是每个 SQL 映射文件了
注意:
-
常用使用相对于类路径的资源引用
-
将包内的映射器接口实现全部注册为映射器和使用映射器接口实现类的完全限定类名要求mapper文件与接口名一致
日志
STDOUT_LOGGING
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
标准(默认)的日志工厂实现,不需要导入依赖,但是只是控制台打印出日志
Log4j
Log4j是Apache的一个开源项目,通过使用Log4j
- 可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;
- 我们也可以控制每一条日志的输出格式;
- 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
- 可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。(重点)
1.log4j简单配置文件
#将等级为DEBUG的日志信息输出到console file这两个目的地,console file的定,又在下面的代码
1og4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
1og4j.appender.console = org.apache.1og4j.ConsoleAppender
1og4j.appender.console.Target = System.out
1og4j.appender.console.Threshold=DEBUG
1og4j.appender.console.layout = org.apache.1og4j.PatternLayout
1og4j.appender.console.layout.ConversionPattern=[%c ]-%m%n
#文件输出的相关设周
1og4j.appender.file = org.apache.1og4j.RollingFileAppender
1og4j.appender.file.File= ./1og/kuang.1og
1og4j.appender.file.MaxFileSize=10mb #超过10MB自动分页
1og4j.appender.file.Threshold=DEBUG
1og4j.appender.file.layout=org. apache .1og4j . PatternLayout
1og4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
1og4j.logger.org.mybatis=DEBUG
1og4j.logger.java.sq1=DEBUG
1og4j.logger.java.sql.Statement=DEBUG
1og4j.logger.java.sql.ResultSet=DEBUG
1og4j.logger.java.sq1.PreparedStatement=DEBUG
2.配置
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
可能出现如下bug
log4j:WARN No appenders could be found for logger (org.apache.ibatis.logging.LogFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
错误解读
如果找不到默认配置文件log4j.properties和log4j.xml,并且应用程序不执行显式配置,就会发生这种情况。log4j使用Thread.getContextClassLoader().getResource()定位默认配置文件,而不直接检查文件系统。要知道放置log4j.properties或log4j.xml的适当位置,就需要了解使用中的类加载器的搜索策略。log4j不提供默认配置,因为在某些环境中可能禁止输出到控制台或文件系统。
-
未引入log4j的依赖
-
未配置log4j.properties文件
-
properties文件格式存在问题
http://www.toyaml.com/ properties文件格式转化工具
仍然有还出现警告
手动写一个初始化的方法吧,一劳永逸。
package util;
import org.apache.log4j.PropertyConfigurator;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class initLogRecord {
public static void initLog() {
FileInputStream fileInputStream = null;
try {
Properties properties = new Properties();
fileInputStream = new FileInputStream("src/main/resources/log4j.properties");
properties.load(fileInputStream);
PropertyConfigurator.configure(properties);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
实际上,最重要的就是
fileInputStream = new FileInputStream(“src/main/resources/log4j.properties”);
根据自己的需要指定这个配置文件的路径吧。
记得在运行主程序之前,调用这个方法进行log4j的初始化!!!
initLogRecord. initLog() ;
Lombok插件
@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
experimental @var
@UtilityClass
Lombok config system
省略get,set,构造器,toString等函数的定义,简化了很多不必要的代码,但是牺牲了可读性
结果映射(resultMap)
-
constructor
用于在实例化类时,注入结果到构造方法中
idArg
- ID 参数;标记出作为 ID 的结果可以帮助提高整体性能arg
- 将被注入到构造方法的一个普通结果
-
id
–一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能
-
result
–注入到字段或 JavaBean 属性的普通结果
-
association
一个复杂类型的关联;许多结果将包装成这种类型
- 嵌套结果映射 – 关联可以是
resultMap
元素,或是对其它结果映射的引用
- 嵌套结果映射 – 关联可以是
-
collection
一个复杂类型的集合
- 嵌套结果映射 – 集合可以是
resultMap
元素,或是对其它结果映射的引用
- 嵌套结果映射 – 集合可以是
-
discriminator
– 使用结果值来决定使用哪个resultMap
-
case
– 基于某些值的结果映射
- 嵌套结果映射 –
case
也是一个结果映射,因此具有相同的结构和元素;或者引用其它的结果映射
- 嵌套结果映射 –
-
1.可以处理数据库字段值与实体类属性不一致情况
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stu.dao.StuMapper">
<resultMap id="Student" type="Student">
<result property="id" column="id"></result>
<result property="name" column="name"></result>
<result property="password" column="pwd"></result>
</resultMap>
<select id="getAllStu" resultType="AliasStudent" resultMap="StudentMap">
select * from Student.students
</select>
</mapper>
其中,property是实体类的属性名,column是数据库的字段名
2.处理复杂属性
注解的使用
多对一问题
当出现如下问题时:
数据库存在两张表,student表和teacher表,student存在teacher字段值tid(外键依赖),通过查询student的sid查询老师的tname
思路一:按照查询嵌套处理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yh6CSYwq-1646317425402)(C:/Users/wp990/AppData/Roaming/Typora/typora-user-images/image-20211011144950648.png)]
思路二:按照结果嵌套处理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TdWa41Sv-1646317425403)(C:/Users/wp990/AppData/Roaming/Typora/typora-user-images/image-20211011145422673.png)]
一对多问题、
按照结果嵌套查询
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AA0BGiR2-1646317425404)(C:/Users/wp990/AppData/Roaming/Typora/typora-user-images/image-20211011151703955.png)]
按照查询嵌套处理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pQ7Om19s-1646317425404)(C:/Users/wp990/AppData/Roaming/Typora/typora-user-images/image-20211011152450923.png)]
小结
关联:association (多对一)
集合:collection(一对多)
javaType ofType区别
- javaType :用来指定实体类的类型
- ofType:用来指定映射到List或者集合中的POJO类型,泛型中的约束类型
动态SQL
- 动态 SQL 是 MyBatis 的强大特性之一
- 动态SQL就是指根据不同的条件生成不同的SQL语句
- 动态SQL,本质还是SQL语句,只是我们可以在SQL层面,执行一个逻辑代码
if
choose (when, otherwise)
trim (where, set)
SQL片段
将部分SQL语句片段提取出来
1.在sql标签中编写SQL片段
<sql id="XXX">
...
</sql>
2.在需要使用的地方使用include标签即可
select * from Student
<where>
<include refid="XXX"></include>
</where>
注意事项:
-
最好基于表单来定义SQL片段
-
不要存在where标签
foreach
缓存
问题背景:当我们需要查询数据时,需要链接数据库,当我们查询的次数过多时,会不停的开关数据库,会耗大量资源
一次查询的结果,给他暂存在一个可以直接取到的地方 ———》内存:缓存
我们再次查询相同的数据时,直接走缓存,就不需要走数据库了
1.什么是缓存(Cache)
- 存在内存中的临时数据
- 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库文件)查询,从缓存中查询,从而提高效率,解决了高并发系统的性能问题
2.为什么使用缓存?
- 减少和数据库的交互次数,减少系统开销,提高系统效率
(有机会了解读写分离,主从复制)
3.什么样的数据库能使用缓存?
- 经常查询并且不经常改变的数据
一级缓存
二级缓存
自定义缓存
软引用弱应用