mybatis详解----有这一篇就够了!!!
mybatis
1. 简介
1.1 mybatis概述
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了[google code](https://baike.baidu.com/item/google code/2346604),并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
使用其,需要引入依赖
(x.x.x 指版本 在maven仓库寻找合适版本)
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
持久层
数据持久化
- 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
- 内存 :断电及失
- 数据库(jdbc)io文件持久化
为什么要有持久化?
因为内存有断电及失的特性。但有些对象我们不能将其丢失,所有出现持久化。
2 第一个mybatis程序
思路
- 搭建环境
- 导入mybatis
- 编写代码
- 测试
2.1 搭建环境
搭建数据库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6nI0sYSp-1623898172572)(C:\Users\李晓冰\AppData\Roaming\Typora\typora-user-images\image-20210615143740211.png)]
创建maven项目
导入依赖
2.2 导入mybatis配置文件
编写mybatis的核心配置文件 在resources中创建xml文件 mybatis-config
XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(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>
<!-- 导入mapper.xml配置文件,里面配置了SQL语句和DAO接口的映射关系,每个map都要在核心配置文件注册-->
<mappers>
<mapper resource="mapper.xml"/>
</mappers>
</configuration>
在resource创建mapper包,在此包中根据需要创建与dao成对应的XXXmapper.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">
<!--SQL语句配置文件,需要在mybatis配置文件中进行加载-->
<!--mapper标签用于做SQL语句和方法之间的映射-->
<!--一个mapper对应一个类,namespace里面写的是dao接口的完整路径-->
<mapper namespace="com.nuc.dao.UserDao">
<!--select的id是方法名-->
<!--resultType是查询的结果的一种映射,User类的属性与列名完全一致(bean类),所以查询的结果会转换成User类-->
<select id="getAll" resultType="User类的完整路径:包名.类名">
/具体的sql语句/
select * from usertest
</select>
</mapper>
2.3 编码
pojo层
写入一个user类
dao层----与mapper对应 要在namespace写入对应全类名
import com.nuc.pojo.User;
import java.util.List;
public interface UserDao {
List<User> getAll();
Service层
ServiceImpl层
2.4 测试
public class Test {
public static void main(String[] args) throws Exception {
//加载配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//得到sqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = builder.build(reader);
//得到sqlSession
SqlSession sqlSession = build.openSession();
//操作sql 传入参数:类名.方法名
List<User> list = sqlSession.selectList("com.nuc.dao.UserDao.getAll");
//遍历
for (User u : list){
System.out.println(u);
}
//关闭资源
sqlSession.close();
reader.close();
}
}
3 crud(增删改查)
1 insert
增加语句;
- id:就是对应的namespace中的方法名;
- resultType : Sql语句执行的返回值;
- parameterType : 参数类型;
<!--namespace=绑定一个指定的Dao/Mapper接口-->
<mapper namespace="com.nuc.dao.UserDao">
<select id="getAll" resultType="com.nuc.pojo.User" >
select * from USER
</select>
</mapper>
步骤 :
- 编写接口
public interface UserMapper {
//插入用户
public void addUser(User user);
}
-
编写对应的mapper中的sql语句
<insert id="addUser" parameterType="com.nuc.pojo.User"> insert into user (id,name,password) values (#{id}, #{name}, #{password}) </insert>
3. 测试
@Test public void test2() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = new User(1,"望埠","123"); mapper.addUser(user); //增删改一定要提交事务 sqlSession.commit(); //关闭sqlSession sqlSession.close(); }
2. select
<select id="getAll" resultType="com.nuc.pojo.User">
select * from USER
</select>
3. update
<update id="updateUser" parameterType="User">
update user set name=#{name},pwd=#{pwd} where id=#{id}
</update>
4. Delete
<delete id="delectUser" parameterType="java.lang.String">
delete from user where name = #{name}
</delete>
注意 增删改一定要提交事务:sqlSession.commit();
Map
当我们的实体类,或数据库中的表参数过多,我们应该使用map
<insert id="addUser2" parameterType="map">
insert into user (id,name)
values (#{userid},#{username});
</insert>
测试:
@Test
public void test02() throws IOException {
//加载配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//得到sqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = builder.build(reader);
//得到sqlSession
SqlSession sqlSession = build.openSession();
Map<String,Object> map = new HashMap<>();
map.put("userid",5);
map.put("username", "jj");
sqlSession.insert("com.nuc.dao.UserDao.addUser2",map);
sqlSession.commit();
//关闭sqlSession
sqlSession.close();
}
注意 :提交事务
Map传递参数,直接在sql中取出key即可! 【parameter=“map”】
对象传递参数,直接在sql中取出对象的属性即可! 【parameter=“Object”】
只有一个基本类型参数的情况下,可以直接在sql中取到
多个参数用Map , 或者注解!
模糊查询
1 在java代码执行时,传递通配符
接口:
List<User> selectlike(String value);
map
<select id="selectlike" resultType="com.nuc.pojo.User" parameterType="java.lang.String">
select * from user where name like #{value}
</select>
测试:
@Test
public void test() throws IOException {
//加载配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//得到sqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = builder.build(reader);
//得到sqlSession
SqlSession sqlSession = build.openSession();
List<User> list = sqlSession.selectList("com.nuc.dao.UserDao.selectlike","%李%");
for (User user : list) {
System.out.println(user.toString());
}
//关闭sqlSession
sqlSession.close();
}
2.在sql拼接使用通配符
<select id="selectlike" resultType="com.nuc.pojo.User" parameterType="java.lang.String">
select * from user where name like “%”#{value}“%”
</select>
mybatis的xml配置
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:
configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
1.环境配置environments
记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
<environments default="development">
<!--通过default 来选择需要的环境的id来控制环境-->
<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>
2.事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]")
3.数据源(dataSource)
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
- 大多数 MyBatis 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。
有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]")
mybatis默认事务管理器jdbc 连接池 POOLED
4. 属性(properties)
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置:
步骤:
- 可以在resource中创建db.properties文件,用于存放属性
driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8&appserverTimezone=UTC
username =root
password = root
2. 在核心配置文件映入
<!--引入外部配置文件-->
<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>
- 可以直接引入外部文件
- 可以在其中增加一些属性配置
- 如果两个文件有同一个字段,优先使用外部配置文件的
5. 类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。如mapper中返回值类型的全限定类名
<!--给实体类起名-->
<typeAliases>
<typeAlias type="com.nuc.pojo.User" alias="user"></typeAlias>
</typeAliases>
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:
<typeAliases>
<package name="com.nuc.pojo" />
</typeAliases>
扫描实体类的包,他的默认别名就是这个类的类名,首字母小写
但若在实体类上有注解,则别名为其注解值。见下面的例子:
@Alias("author")
public class Author {
...
}
6设置(settings)
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。
7.映射器(mappers)
MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:///
形式的 URL),或类名和包名等。
现在主要用以下方法实现
第一种
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="com/nuc/Mapper/UserMapper.xml"/>
<mapper resource="com/nuc/Mapper/PersonMapper.xml"/>
</mappers>
第二种
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="com.nuc.pojo"/>
</mappers>
第三种
<!--每一个Mapper.xml都需要在MyBatis核心配置文件中注册-->
<mappers>
<mapper class="com.kuang.dao.UserMapper"/>
</mappers>
**注意点:**第二种和第三种方法
- 接口和他的Mapper配置文件必须同名
- 接口和他的Mapper配置文件必须在同一个包下
8.生命周期和作用域
作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。
SqlSessionFactoryBuilder:
-
一旦创建了SqlSessionFactory,就不再需要它了
-
局部变量
SqlSessionFactory:
-
说白了就可以想象为:数据库连接池
SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建一个实例。因此SqlSessionFactory的最佳作用域是应用作用域(ApplocationContext)。 -
最简单的就是使用单例模式或静态单例模式。
SqlSession:
-
连接到连接池的一个请求
-
SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
-
用完之后需要赶紧关闭,否则资源被占用!
解决用户属性名与数据库字段名不匹配问题
当累的属性为:
private int id;
private String name;
private String password;
数据库字段名为
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wAkPk4dR-1623898172574)(C:\Users\李晓冰\AppData\Roaming\Typora\typora-user-images\image-20210616184127087.png)]
用User接收无法接收到password属性
解决 方法:
-
起别名
<select id="getAll" resultType="aaa"> select id,name,pwd as password from USER </select>
-
使用resultMap
resultMap是一个结果集映射
<!--结果集映射-->
<resultMap id="UserMap" type="User">
<!--column数据库中的字段,property实体类中的属性-->
<!-- 相同的可以不去写,只用关注不同的
<result column="id" property="id"></result>
<result column="name" property="name"></result>-->
<result column="pwd" property="password"></result>
</resultMap>
<select id="getUserList" resultMap="UserMap">
select* from USER
</select>
-
resultMap 元素是 MyBatis 中最重要最强大的元素。
-
ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
-
ResultMap 的优秀之处——你完全可以不用显式地配置它们。
-
如果这个世界总是这么简单就好了(尤其是找对象)
日志
如果一个数据库操作,出现了异常,我们需要排错,日志就是最好的纠错助手
曾经:sout输出、debug
现在:日志工厂
- SLF4J
- **LOG4J ** (使用要导包)
- LOG4J2
- JDK_LOGGING
- COMMONS_LOGGING
- STDOUT_LOGGING
- NO_LOGGING
在MyBatis中具体使用哪一个日志实现,在设置中设定
STDOUT_LOGGING
<!-- 标准的日志工厂实现-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
注意 是logImpl ,Impl的i是大写的,不能有一点错,也不能有空格。
log4j
- 简介:
Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
-
使用
2.1 导包
<!-- 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/lxb.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
- 3在核心配置文件配置
<settings> <setting name="logImpl" value="LOG4J"/> </settings>
2.4 在要使用log4j的類中使用
import org.apache.log4j.Logger; import org.junit.jupiter.api.Test; public class UserTest { static Logger logger = Logger.getLogger(UserTest.class); //括號内跟本类的。class @Test public void test(){ logger.info("info: 测试log4j"); logger.debug("debug: 测试log4j"); logger.error("error:测试log4j"); } }
运行完后生成log4j文件
分页
1. 使用Limit分页
SELECT * from user limit startIndex,pageSize
下面是每页显示4个 从0开始查
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4QuVIsmn-1623898172576)(C:\Users\李晓冰\AppData\Roaming\Typora\typora-user-images\image-20210616204351239.png)]
# 相当于SELECT * from user limit 0,3
SELECT * from user limit 3
2. 使用rowbounds分页
不再使用SQL实现分页,通过java代码实现
接口
List<User> getUserByRowBounds();
mapper
<select id="getUserByRowBounds">
select * from user
</select>
测试
@Test
public void getUserByRowBounds(){
//加载配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//得到sqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = builder.build(reader);
//得到sqlSession
SqlSession sqlSession = build.openSession();
//RowBounds实现 从下表一开始,每页显示2个
RowBounds rowBounds = new RowBounds(1, 2);
//通过Java代码层面实现分页
List<User> userList = sqlSession.selectList("com.kaung.dao.UserMapper.getUserByRowBounds", null, rowBounds);
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
3.通过插件
mybatis分页插件pageHelper
使用说明文档
使用注解开发
上一篇: ViewPager指示器有这一篇就够了