文章目录
我亦无他,唯手熟尔。
时间:2023年5月2日12:41:27
新手入门,如有错误及疑问,欢迎指出。
MyBatis介绍
- MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发
- MyBatis 本是 Apache 的一个开源项目iBatis,2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,2013年11月迁移到Github
官网:https://mybatis.org/mybatis-3/zh/index.html
持久层
- 负责将数据到保存到数据库的那一层代码
- JavaEE三层架构:表现层、业务层、持久层
框架
- 框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型
- 在框架的基础之上构建软件编写更加高效、规范、通用、可扩展
JDBC缺点
MyBatis简化
MyBatis快速入门之查询user表中的所有数据
1、创建user表,添加数据
create database mybatis;
use mybatis;
drop table if exists tb_user;
create table tb_user(
id int primary key auto_increment,
username varchar(20),
password varchar(20),
gender char(1),
addr varchar(30)
);
INSERT INTO tb_user VALUES (1, 'zhangsan', '123', '男', '北京');
INSERT INTO tb_user VALUES (2, '李四', '234', '女', '天津');
INSERT INTO tb_user VALUES (3, '王五', '11', '男', '西安');
2、创建模块,导入坐标
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</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.13</version>
<scope>test</scope>
</dependency>
<!-- 添加slf4j日志api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.20</version>
</dependency>
<!-- 添加logback-classic依赖 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- 添加logback-core依赖 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<!--logback.xml 放在resources文件夹下-->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--
CONSOLE :表示当前的日志信息是可以输出到控制台的。
-->
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%level] %blue(%d{HH:mm:ss.SSS}) %cyan([%thread]) %boldGreen(%logger{15}) - %msg %n</pattern>
</encoder>
</appender>
<logger name="com.wly" level="DEBUG" additivity="false">
<appender-ref ref="Console"/>
</logger>
<!--
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
, 默认debug
<root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制。
-->
<root level="DEBUG">
<appender-ref ref="Console"/>
</root>
</configuration>
3、编写MyBatis核心配置文件(mabatis-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>
<typeAliases>
<package name="com.wly.pojo"/>
</typeAliases>
<!--
environments:配置数据库连接环境信息,可以配置多个environment,
通过default属性切换不同的environment
-->
<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/mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--加载sql映射文件-->
<!--<mapper resource="com/wly/mapper/UserMapper.xml"/>-->
<!--Mapper代理方式-->
<package name="com.wly.mapper"/>
</mappers>
</configuration>
4、编写SQL映射文件 --> 同一管理sql语句,解决硬编码问题
UserMapper.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">
<!--
namespace:名称空间
-->
<mapper namespace="test">
<select id="selectAll" resultType="com.wly.pojo.User">
select * from tb_user;
</select>
<select id="selectById" resultType="user">
select * from tb_user where id = #{id};
</select>
</mapper>
public interface UserMapper {
List<User> selectAll();
User selectById(int id);
}
5、编码
- 定义POJO类
- 加载核心配置文件,获取AqlSessionFactory对象
- 获取SqlSession对象,执行SQL
- 释放资源
GPT:
在Maven工程中,POJO是指"Plain Old Java Object",翻译成中文即为“普通的Java对象”。POJO是一种轻量级的Java对象,没有任何限制或者必须继承某个复杂框架或实现某个接口,其本质上就是一个普通的Java类,仅仅是提供对类的属性访问方法(getters/setters方法)和默认构造函数的实现。POJO类通常用来表示业务实体,在Maven工程中,POJO作为数据对象被应用于各种业务场景中,例如存储数据、传递数据等。
POJO简单易懂、易于维护,也更加灵活,同时也避免了强依赖于一个特定的框架。
SqlSessionFactory 是 MyBatis 框架的核心接口之一,它负责启动 MyBatis 应用程序中的数据库连接和事务管理。
MyBatis 的 SqlSessionFactory 是一个建议的线程安全对象,它是数据访问层中最重要的一个类。SqlSessionFactory 负责创建 SqlSession 对象,并对数据库进行配置和管理,由于 SqlSession 产生的成本比较高,因此 SqlSessionFactory 的实例通常被应用程序缓存起来,以便反复使用。
SqlSessionFactory 接口的实现类 SqlSessionFactoryImpl 提供了一个静态方法 build()。该方法用于从 MyBatis 配置文件中构建 SqlSessionFactory 实例。具体而言,MyBatis 会读取核心配置文件 mybatis-config.xml,在其中配置 SqlSessionFactory 和其他配置信息。在使用 MyBatis 框架时,我们需要通过上述 build() 方法获取 SqlSessionFactory 实例并调用它的 openSession() 方法获取 SqlSession 实例,然后使用 SqlSession 对象进行数据库操作。
public class MyBatisDemo {
public static void main(String[] args) throws IOException {
//1.加载mybatis的核心配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3.执行sql
List<User> users = sqlSession.selectList("test.selectAll");
System.out.println(users);
//4. 释放资源
sqlSession.close();
}
}
使用Mapper代理方式完成
1、定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放在同一目录下
2、设置SQL映射文件的namespace
属性为Mapper接口全限定名
3、在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一直
4、编码
1、通过SqlSession的getMapper方法获取Mapper接口的代理对象
2、通过调用方法完成sql的执行
细节: 如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载
// 获取UserMapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.selectAll();
MyBatis核心配置文件概述
environments标签
数据库环境的配置,支持多环境配置
其中,事务管理器(transactionManager)类型有两种:
- JDBC:这个配置就是直接使用了JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
- MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false来阻止它默认的关闭行为。
其中,数据源(dataSource)类型有三种:
- UNPOOLED:这个数据源的实现只是每次被请求时打开和关闭连接。
- POOLED:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来。
- JNDI:这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI上下文的引用。
mapper标签
该标签的作用是加载映射的,加载方式有如下几种:
使用相对于类路径的资源引用,例如:
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
使用完全限定资源定位符(URL),例如:
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
使用映射器接口实现类的完全限定类名,例如:
<mapper class="org.mybatis.builder.AuthorMapper"/>
将包内的映射器接口实现全部注册为映射器,例如:
<package name="org.mybatis.builder"/>
Properties标签
实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件,该标签可以加载额外配置的properties文件
typeAliases标签
mybatis框架已经为我们设置好的一些常用的类型的别名
MyBatis相应API
SqlSession工厂构建器SqlSessionFactoryBuilder
常用API:SqlSessionFactory build(InputStream inputStream)
通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象
// 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
其中, Resources 工具类,这个类在 org.apache.ibatis.io 包中。Resources 类帮助你从类路径下、文件系统或一个 web URL 中加载资源文件。
SqlSession工厂对象SqlSessionFactory
SqlSessionFactory 有多个个方法创建 SqlSession 实例。常用的有如下两个:
SqlSession会话对象
SqlSession 实例在 MyBatis 中是非常强大的一个类。在这里你会看到所有执行语句、提交或回滚事务和获取映射器实例的方法。
执行语句的方法主要有:
<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)
操作事务的方法主要有:
void commit()
void rollback()
MyBatisX 插件
MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
主要功能:
- XML 和 接口方法 相互跳转
- 根据接口方法生成
statement
安装:
实践案例-查询所有数据
-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand
(
-- id 主键
id int primary key auto_increment,
-- 品牌名称
brand_name varchar(20),
-- 企业名称
company_name varchar(20),
-- 排序字段
ordered int,
-- 描述信息
description varchar(100),
-- 状态:0:禁用 1:启用
status int
);
-- 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1);
SELECT * FROM tb_brand;
1、编写接口方法
- 参数:无
- 结果:List
/**
* 查询所有
*/
List<Brand> selectAll();
2、编写SQL语句:SQL映射文件
<select id="selectAll" resultType="Brand">
select *
from tb_brand;
</select>
3、执行方法,测试
实体类属性名 和 数据库表列名 不一致,不能自动封装数据
- 起别名:在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样可以定义 片段,提升复用性
resultMap
:定义<resultMap>
完成不一致的属性名和列名的映射
<select id="selectAll" resultType="Brand">
select id, brand_name as brandName, company_name as companyName, ordered, description, status
from tb_brand;
</select>
<?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.wly.mapper.BrandMapper">
<!--
数据库表的字段名称和实体类的属性名称不一样
则不能自动封装数据。
方式1:起别名,对不一样的列名起别名,让别名和实体类的属性名一样.缺点:每次查询都要定义一次别名
方式2:resultMap
1、定义<resultMap>标签
2、在<select>标签中,使用resultMap属性替换resultType属性
-->
<!--
id:唯一标识
type:映射的类型,支持别名
-->
<resultMap id="brandResultMap" type="brand">
<!--
id:完成主键字段的映射
result:完成一般字段的映射
-->
<result column="brand_name" property="brandName"/>
<result column="company_name" property="companyName"/>
</resultMap>
<select id="selectAll" resultMap="brandResultMap">
select *
from tb_brand;
</select>
<!--方式1:起别名-->
<!--<select id="selectAll" resultType="Brand">
select id, brand_name as brandName, company_name as companyName, ordered, description, status
from tb_brand;
</select>-->
<!--使用sql片段替代上述过长字符串-->
<!--sql片段 缺点:不灵活-->
<!--<sql id="brand_column">
id, brand_name as brandName, company_name as companyName, ordered, description, status
</sql>
<select id="selectAll_1" resultType="Brand">
select
<include refid="brand_column"/>
from tb_brand;
</select>-->
<!--不起别名的话,由于名字不一样会有缺失值-->
<!--<select id="selectAll" resultType="Brand">
select *
from tb_brand;
</select>-->
<select id="selectById" resultMap="brandResultMap">
select *
from tb_brand where id = #{id}
</select>
<!--
条件查询
-->
<select id="selectByCondition" resultMap="brandResultMap">
select *
from tb_brand
where
status = #{status}
and company_name like #{companyName}
and brand_name like #{brandName}
</select>
</mapper>
实践案例-查看详情
1、编写接口方法:Mapper接口
- 参数:id
- 结果:Brand
/**
* 查看详情:根据Id查询
*/
Brand selectById(int id);
2、编写SQL语句:SQL映射文件
<select id="selectById" resultMap="brandResultMap">
select *
from tb_brand where id = #{id}
</select>
3、执行方法,测试
@Test
public void testSelectById() throws IOException {
//接收参数
int id = 2;
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
Brand brand = brandMapper.selectById(id);
System.out.println(brand);
sqlSession.close();
}
总结:
- 参数占位符:
1)#{}
:执行SQL时,会将#{}占位符替换为?,将来自动设置参数值
2)${}
:拼SQL。会存在SQL注入问题
3)使用时机:
参数传递,都使用#{}
如果要对表名、列名进行动态设置,只能使用${}
进行sql拼接。 parameterType
:- 用于设置参数类型,该参数可以省略
- SQL 语句中特殊字符处理:
- 转义字符
<![CDATA[ 内容 ]]>
:CD提示
实践案例-多条件查询
1、编写接口方法:Mapper接口
- 参数:所有查询条件
- 结果:List
List<Brand> selectByCondition(@Param("status")int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
List<Brand> selectByCondition(Brand brand);
List<Brand> selectByCondition(Map map);
2、编写SQL语句:SQL映射文件
<!--
条件查询
-->
<select id="selectByCondition" resultMap="brandResultMap">
select *
from tb_brand
where
status = #{status}
and company_name like #{companyName}
and brand_name like #{brandName}
</select>
3、执行方法,测试
SQL语句设置多个参数有几种方式?
- 散装参数:如果方法中有多个参数,需要使用
@Param("SQL中的参数名称")
使用麻烦 - 实体类封装参数
只需要保证SQL中的参数名 和 实体类属性名对应上,即可设置成功 - map集合
只需要保证SQL中的参数名 和 map集合的键的名称对应上,即可设置成功