文章目录
一、Mybatis简介
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。——From Baidu encyclopedia
Mybatis官方中文文档:https://mybatis.org/mybatis-3/zh/index.html
Maven仓库:https://mvnrepository.com/artifact/org.mybatis/mybatis
Q:什么是持久化?
A:数据持久化,即将程序的数据在持久状态和瞬时状态转化的过程。
Q:什么是持久层?
A:完成持久化工作的代码块,层的界限是十分明显的。
Q:Mybatis优点?
A:
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射。
- 提供对象关系映射标签,支持对象关系组建维护。
- 提供xml标签,支持编写动态sql。
二、基础使用流程
-
创建父项目
-
导入依赖
<!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.1</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.22</version> </dependency>
-
创建子项目
-
在resources中创建Mybatis配置文件,文件名一般默认为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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/computer03?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="niushijian"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/ola/dao/AuthorMapper.xml"/> </mappers> </configuration>
-
编写工具类MybatisUtils
package com.ola.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.IOException; import java.io.InputStream; /** * ClassName:MybatisUtils Package:com.ola.utils * * @author morningj * @date 2021/1/10 15:39 */ public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory; static { try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(); } }
-
编写代码
-
实体类
package com.ola.pojo; /** * ClassName:Author Package:com.ola.pojo * * @author morningj * @date 2021/1/10 15:50 */ public class Author { private String AuthorID; private String Name; public Author(String authorID, String name) { AuthorID = authorID; Name = name; } public Author() {} @Override public String toString() { return "Author{" + "AuthorID='" + AuthorID + '\'' + ", Name='" + Name + '\'' + '}'; } public String getAuthorID() { return AuthorID; } public void setAuthorID(String authorID) { AuthorID = authorID; } public String getName() { return Name; } public void setName(String name) { Name = name; } }
-
Dao接口
package com.ola.dao; import com.ola.pojo.Author; import java.util.List; /** * ClassName:AuthorDao Package:com.ola.dao * * @author morningj * @date 2021/1/10 15:52 */ public interface AuthorDao { List<Author> getAuthorList(); }
-
AuthorMapper.xml(即原来的Dao接口实现类)
<?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.ola.dao.AuthorDao"> <select id="getAuthorList" resultType="com.ola.pojo.Author"> select * from computer03.Name </select> </mapper>
对命名空间的补充
命名空间的作用有两个,一个是利用更长的全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。就算你觉得暂时用不到接口绑定,你也应该遵循这里的规定,以防哪天你改变了主意。 长远来看,只要将命名空间置于合适的 Java 包命名空间之中,你的代码会变得更加整洁,也有利于你更方便地使用 MyBatis。
命名解析
为了减少输入量,MyBatis 对所有具有名称的配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。
- 全限定名(比如 “com.mypackage.MyMapper.selectAllThings)将被直接用于查找及使用。
- 短名称(比如 “selectAllThings”)如果全局唯一也可以作为一个单独的引用。 如果不唯一,有两个或两个以上的相同名称(比如 “com.foo.selectAllThings” 和 “com.bar.selectAllThings”),那么使用时就会产生“短名称不唯一”的错误,这种情况下就必须使用全限定名。
-
-
测试
package com.ola.dao; import com.ola.pojo.Author; import com.ola.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.List; /** * ClassName:AuthorDaoTest Package:com.ola.dao * * @author morningj * @date 2021/1/10 16:08 */ public class AuthorDaoTest { @Test public void test() { // 获取session对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); // 方式一 AuthorDao mapper = sqlSession.getMapper(AuthorDao.class); List<Author> authorList = mapper.getAuthorList(); // 方式二(不推荐使用) // List<Author> authorsList = sqlSession.selectList("com.ola.dao.AuthorDao.getAuthorList"); // for (Author author : authorsList) { // System.out.println(author); // } for (Author author : authorList) { System.out.println(author); } sqlSession.close(); } }
可能遇到的问题
- 配置文件没有注册
- 绑定接口错误
- 方法名不对
- 返回类型不对
- url写错
- 由于权限问题resources中的配置文件无法导出
对象生命周期和作用域
错误使用会导致非常严重的并发问题!
三、使用XML配置实现CRUD
- namespace
- select
- id:就是对应的namespace中的方法名
- resultType:返回的类型,例如:com.ola.pojo.Author
- parameterType:参数类型
INSERT:注意增删改需要提交事务,才能完成增删改操作!!!
<insert id="addAuthor" parameterType="com.ola.pojo.Author">
insert into computer03.Name(AuthorID, Name)
values (#{AuthorID}, #{Name});
</insert>
@Test
public void addAuthor() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
mapper.addAuthor(new Author("12345678-1", "olarian"));
sqlSession.commit();
sqlSession.close();
}
UPDATE:注意增删改需要提交事务,才能完成增删改操作!!!
<update id="updateAuthor" parameterType="com.ola.pojo.Author">
update computer03.Name
set AuthorID =#{AuthorID},
Name=#{Name}
where AuthorID = #{AuthorID};
</update>
@Test
public void updateAuthor() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
mapper.updateAuthor(new Author("12345678-1", "ola"));
sqlSession.commit();
sqlSession.close();
}
DELETE:注意增删改需要提交事务,才能完成增删改操作!!!
<delete id="deleteAuthor" parameterType="String">
delete
from computer03.Name
where AuthorID = #{id};
</delete>
@Test
public void deleteAuthor() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
mapper.deleteAuthor("12345678-1");
sqlSession.commit();
sqlSession.close();
}
四、配置解析
官方文档:https://mybatis.org/mybatis-3/zh/configuration.html
-
核心配置文件(在xml中严格遵守以下顺序)
- mybatis-config.xml
- mybatis的配置文件包含了会深深影响Mybatis行为的设置和属性信息
- properties(属性):这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置.【db.properties】
- settings(设置):这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器):在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]")
- dataSource(数据源):有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]")
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
-
properties(属性):这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置.【db.properties】
优先级:外部配置文件>内部属性引入
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/computer03?useSSL=true&useUnicode=true&characterEncoding=UTF-8 username=root password=niushijian
在核心配置文件中引入:
<!--注意,在xml文件中,标签是有先后顺序的,放错顺序会报错,properties放在configuration的首位--> <properties resource="db.properties"/>
<environment id="test"> <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>
-
typeAliases(类型别名)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
<select id="getAuthorList" resultType="com.ola.pojo.Author"> select * from computer03.Name </select> <select id="getAuthorById" resultType="com.ola.pojo.Author" parameterType="String"> select * from computer03.Name where AuthorID = #{id}; </select> <insert id="addAuthor" parameterType="com.ola.pojo.Author"> insert into computer03.Name(AuthorID, Name) values (#{AuthorID}, #{Name}); </insert> <update id="updateAuthor" parameterType="com.ola.pojo.Author"> update computer03.Name set AuthorID =#{AuthorID}, Name=#{Name} where AuthorID = #{AuthorID}; </update> <delete id="deleteAuthor" parameterType="String"> delete from computer03.Name where AuthorID = #{id}; </delete>
这里的parameterType和resultType都需要完全限定名,这就产生了冗余,为解决这个问题,使用typeAliases!
<typeAliases> <typeAlias type="com.ola.pojo.Author" alias="Author"/> </typeAliases>
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,例如:
<typeAliases> <package name="com.ola.pojo"/> </typeAliases>
每一个在包
domain.blog
中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如domain.blog.Author
的别名为author
;若有注解,则别名为其注解值。@Alias("author") public class Author { ... }
-
settings(设置):这是 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
(orvalue
) 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>
-
mappers(映射器)
-
方式一:使用相对于类路径的资源引用(推荐)
<mappers> <mapper resource="com/ola/dao/AuthorMapper.xml"/> </mappers>
-
方式二:使用映射器接口实现类的完全限定类名(不推荐,会出问题,如:不在一个包下;类名和xml名不同)
<mappers> <mapper class="com.ola.dao.AuthorMapper"/> </mappers>
-
方式三:将包内的映射器接口实现全部注册为映射器(不推荐,会出问题,如:不在一个包下;类名和xml名不同)
<mappers> <package name="com.ola.dao"/> </mappers>
-
五、ResultMap结果集映射:用来解决属性名和字段名不一致的问题
ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
<resultMap id="AuthorMap" type="Author">
<result column="AuthorID" property="id"/>
</resultMap>
<select id="getAuthorById" parameterType="String" resultMap="AuthorMap">
select *
from computer03.Name
where AuthorID = #{id};
</select>
六、日志
-
日志工厂
如果一个数据库操作出现了异常,我们需要排除错误,就要使用日志!
设置名 描述 有效值 默认值 logPrefix 指定 MyBatis 增加到日志名称的前缀。 任何字符串 未设置 logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设置 - SLF4J
- LOG4J
- LOG4J2
- JDK_LOGGING
- COMMONS_LOGGING
- STDOUT_LOGGING (标准日志输出)
- NO_LOGGING
在Mybatis中具体使用哪个日志需要再settings中设定!
STDOUT_LOGGING (标准日志输出):
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter. PooledDataSource forcefully closed/removed all connections. PooledDataSource forcefully closed/removed all connections. PooledDataSource forcefully closed/removed all connections. PooledDataSource forcefully closed/removed all connections. Opening JDBC Connection Created connection 1008315045. Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3c19aaa5] ==> Preparing: select * from computer03.Name where AuthorID = ?; ==> Parameters: 12345678-1(String) <== Columns: AuthorID, Name <== Row: 12345678-1, olarian <== Total: 1 Author{AuthorID='12345678-1', Name='olarian'} Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3c19aaa5] Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3c19aaa5] Returned connection 1008315045 to pool.
LOG4J:
-
导包
<!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
-
在resources中创建log4j.properties
#将等级为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/Mybatis_study_ola.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
-
在mybatis-config.xml中配置settings为LOG4J日志实现
<settings> <setting name="logImpl" value="LOG4J"/> </settings>
-
LOG4J的使用
- 简单使用
[org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter. [org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter. [org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections. [org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections. [org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections. [org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection [org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 30578394. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da] [com.ola.dao.AuthorMapper.getAuthorById]-==> Preparing: select * from computer03.Name where AuthorID = ?; [com.ola.dao.AuthorMapper.getAuthorById]-==> Parameters: 12345678-1(String) [com.ola.dao.AuthorMapper.getAuthorById]-<== Total: 1 Author{AuthorID='12345678-1', Name='olarian'} [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da] [org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 30578394 to pool.
-
类中使用
// 注意这里导入的Logger包应该为org.apache.log4j.Logger static Logger logger = Logger.getLogger(AuthorMapperTest.class);
@Test public void log4jTest() { logger.info("---------info:进入了TESTLOG4J方法!!---------"); logger.debug("---------debug:进入了TESTLOG4J方法!!---------"); logger.error("---------error:进入了TESTLOG4J方法!!---------"); }
[DEBUG][21-01-11][org.apache.ibatis.logging.LogFactory]Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter. [DEBUG][21-01-11][org.apache.ibatis.logging.LogFactory]Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter. [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections. [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections. [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections. [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections. [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Opening JDBC Connection [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]Created connection 30578394. [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da] [DEBUG][21-01-11][com.ola.dao.AuthorMapper.getAuthorById]==> Preparing: select * from computer03.Name where AuthorID = ?; [DEBUG][21-01-11][com.ola.dao.AuthorMapper.getAuthorById]==> Parameters: 12345678-1(String) [DEBUG][21-01-11][com.ola.dao.AuthorMapper.getAuthorById]<== Total: 1 [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da] [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da] [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]Returned connection 30578394 to pool. [DEBUG][21-01-11][org.apache.ibatis.logging.LogFactory]Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter. [DEBUG][21-01-11][org.apache.ibatis.logging.LogFactory]Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter. [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections. [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections. [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections. [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections. [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Opening JDBC Connection [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]Created connection 30578394. [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da] [DEBUG][21-01-11][com.ola.dao.AuthorMapper.getAuthorById]==> Preparing: select * from computer03.Name where AuthorID = ?; [DEBUG][21-01-11][com.ola.dao.AuthorMapper.getAuthorById]==> Parameters: 12345678-1(String) [DEBUG][21-01-11][com.ola.dao.AuthorMapper.getAuthorById]<== Total: 1 [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da] [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da] [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]Returned connection 30578394 to pool. [INFO][21-01-11][dao.AuthorMapperTest]---------info:进入了TESTLOG4J方法!!--------- [DEBUG][21-01-11][dao.AuthorMapperTest]---------debug:进入了TESTLOG4J方法!!--------- [ERROR][21-01-11][dao.AuthorMapperTest]---------error:进入了TESTLOG4J方法!!---------
七、实现分页
Q:为什么要分页?
A:为了减少数据的处理量
-
使用Limit分页,语法:select * from Table limit startIndex,pageSize;
-
使用Mybatis实现分页
-
接口
List<Author> getAuthorByLimit(Map<String, Integer> map);
-
Mapper.xml
<select id="getAuthorByLimit" resultType="Author" parameterType="map"> select * from computer03.Name limit #{startIndex},#{pageSize}; </select>
-
测试
@Test public void getAuthorByLimit() { SqlSession sqlSession = MybatisUtils.getSqlSession(); AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class); HashMap<String, Integer> map = new HashMap<>(); map.put("startIndex", 0); map.put("pageSize", 15); List<Author> authorByLimit = mapper.getAuthorByLimit(map); for (Author author : authorByLimit) { System.out.println(author); } sqlSession.close(); }
-
-
使用RowBounds实现分页(不推荐使用)
-
接口
List<Author> getAuthorByRowBounds();
-
Mapper.xml
<select id="getAuthorByRowBounds" resultType="Author"> select * from computer03.Name </select>
-
测试
@Test public void getAuthorByRowBounds() { SqlSession sqlSession = MybatisUtils.getSqlSession(); RowBounds rowBounds = new RowBounds(0, 3); List<Author> authorList = sqlSession.selectList("com.ola.dao.AuthorMapper.getAuthorByRowBounds", null, rowBounds); for (Author author : authorList) { System.out.println(author); } sqlSession.close(); }
-
-
使用分页插件 Mybatis PageHelper
-
引入Jar包
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.2.0</version> </dependency>
-
配置拦截器插件
<!-- plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下: properties?, settings?, typeAliases?, typeHandlers?, objectFactory?,objectWrapperFactory?, plugins?, environments?, databaseIdProvider?, mappers? --> <plugins> <!-- com.github.pagehelper为PageHelper类所在包名 --> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 --> <property name="param1" value="value1"/> </plugin> </plugins>
-
分页插件参数介绍
-
八、使用注解开发
底层实现机制:反射(动态代理)
-
增加接口
public interface AuthorMapper { @Select("select * from computer03.Name limit 0,15") List<Author> getAuthors(); }
-
绑定接口
<mappers> <mapper class="com.ola.dao.AuthorMapper"/> </mappers>
-
测试
package com.ola.dao; import com.ola.pojo.Author; import com.ola.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.List; /** * ClassName:authorTest Package:com.ola.dao * * @author morningj * @date 2021/1/11 12:34 */ public class authorTest { @Test public void getAuthors() { SqlSession sqlSession = MybatisUtils.getSqlSession(); AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class); List<Author> authors = mapper.getAuthors(); for (Author author : authors) { System.out.println(author); } sqlSession.close(); } }
Attention: 使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。
九、Mybatis详细执行流程
十、使用注解实现增删改查CRUD
-
SELECT:
@Select("select * from computer03.Name where AuthorID = #{id}") Author getAuthorById(@Param("id") String id);
@Test public void getAuthorById() { SqlSession sqlSession = MybatisUtils.getSqlSession(); AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class); Author authorById = mapper.getAuthorById("12345678-1"); System.out.println(authorById); sqlSession.close(); }
-
INSERT:
- 法一
@Insert("insert into computer03.Name(AuthorID,Name) values(#{id},#{name})") void addAuthor(@Param("id") String authorID, @Param("name") String name);
@Test public void addAuthor() { SqlSession sqlSession = MybatisUtils.getSqlSession(); AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class); mapper.addAuthor("12345678-2", "niushijian"); sqlSession.close(); }
-
法二
@Insert("insert into computer03.Name(AuthorID,Name) values(#{AuthorID},#{Name})") void addAuthor02(Author author);
@Test public void addAuthor() { SqlSession sqlSession = MybatisUtils.getSqlSession(); AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class); mapper.addAuthor02(new Author("12345678-3", "olarional")); sqlSession.close(); }
-
UPDATE:
@Update("update computer03.Name set AuthorID=#{AuthorID},Name=#{Name} where AuthorID=#{AuthorID}") void updateAuthor(Author author);
@Test public void updateAuthor() { SqlSession sqlSession = MybatisUtils.getSqlSession(); AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class); mapper.updateAuthor(new Author("12345678-3", "o")); sqlSession.close(); }
-
DELETE:
@Delete("delete from computer03.Name where AuthorID=#{deleteId}") void deleteAuthor(@Param("deleteId") String id);
@Test public void deleteAuthor() { SqlSession sqlSession = MybatisUtils.getSqlSession(); AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class); mapper.deleteAuthor("12345678-4"); sqlSession.close(); }
关于@Param()注解
- 基本类型的参数或者String类型的参数,需要加上
- 引用类型不需要加
- 如果只有一个基本类型的话,可以忽略,但是还是建议加上
- 我们在SQL中引用的就是我们这里的@Param()中设定的属性名
关于==#{}和${}==的区别
#是预编译的,相当于PreparedStatement!一般会使用#{}来防止SQL注入问题!