MyBatis
- 什么是MyBatis?
- MyBitis本是Apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBitis。2013年11月迁移到Github
- 持久层
- 负责将数据保存到数据库的那一层代码
- javaEE三层架构:表现层,业务层,持久层
- 框架
- 框架就是一个半成品软件,是一套可重用的,通用的,软件基础代码模型
- 在框架的基础之上构建软件编写更加高效,规范,通用,可扩展
- JDBC缺点
- 硬编码
- 注册驱动,获取连接
- SQL语句
- 操作繁琐
- 手动设置参数
- 手动封装结果集
MyBatis快速入门
- 查询user表中所有数据
- 创建user表,添加数据 **//**mysql中创建
create database mybatis;
use mybitis;
drop table if exists tb_user;
create table tb_user(
id int primary key auto_increment.
username varchar(20),
password varchar(20),
gender vhar(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', '男', '西安' );
建议:myBitis官网
- 创建模块,导入坐标
要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可。
如果使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version> //选择版本3.5.7
</dependency>
pom.xml //内含很多依赖包,需要自行添加
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>mybatis-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--mybatis依赖-->
<dependency>
<groupId> org.mybatis </groupId>
<artifactId> mybatis </artifactId>
<version> 3.5.7</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.5.6</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>
</dependencies>
<properties>
<maven.compiler.source>13</maven.compiler.source>
<maven.compiler.target>13</maven.compiler.target>
</properties>
</project>
- 编写MyBitis核心配置文件—>替换连接信息 解决硬编码的问题
XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)
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.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSLL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--加载sql映射文件-->
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
- 编写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.itheima.pojo.User">//id就是查询的名字,resultType就是类的地址
select * from tb_user; //查询语句
</select>
</mapper>
可以查看一下MyBatis得官网里面有详解
- 编码
- 定义POJO类
- 加载核心配置文件,获取SqlSessionFactory对象
- 获取SqlSession对象,执行SQL语句
- 释放资源
User类 获取数据库的数据
package com.itheima.pojo;
public class User {
private Integer id;
private String username;
private String password;
private String gender;
private String addr;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", gender='" + gender + '\'' +
", addr='" + addr + '\'' +
'}';
}
}
MyBatisDemo类 主类
package com.itheima;
import com.itheima.pojo.User;
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;
import java.util.List;
/*
Mybatis快速入门代码
*/
public class MyBatisDemo {
public static void main(String[] args) throws IOException {
//1.加载mybitis的核心配置文件,获取sqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.获取SqlSessionFactory对象,用它来执行sql
SqlSession sqlSession=sqlSessionFactory.openSession();
//3.执行sql
List<User> users = sqlSession.selectList("test.selectAll");
//selectOne查找一个
System.out.println(users);
//4.释放资源
sqlSession.close();
}
}
解决SQL语句警告问题
解决SQL映射文件的警告提示
- 产生原因:Idea和数据库没有建立连接,不识别表信息
- 解决方法:在Idea中配置MYSQL数据库连接
Mapper代理开发
- 目的
- 解决了原生方法中的硬编码
- 简化后期执行SQL
//3.执行sql
List<User> users=sqlSession.selectList("test.selectAll");
//3.获取接口代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//4.执行方法,其实就是执行sql语句
List<User> users = userMapper.selectAll();
- 使用Mapper代理方式完成入门案例
- 定义与SQL文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放在同一目录下
定义resource时,选择目录com/itheima/mapper(不能用.只能用/),将UserMapper.xml文件拖入其中。
- 设置SQL映射文件的namespace属性为Mapper接口全限定名(就是将名称空间改成接口文件位置)
- 在Mapper接口中定义方法,方法名就是SQL映射文件中的sql语句中的id,并且保持参数类型和返回值类型一致
- 编码
- 通过SqlSession的getMapper方法获取Mapper接口的代理对象
- 调用对应方法完成sql的执行
修改一下加载sql映射文件地址(之前把这个映射文件放入com.itheima.mapper文件下)
细节:如果Mapper接口名称和SQL映射文件名称相同,并在同一个目录下,则可以使用包扫描地方式简化SQL映射文件地加载
Mybatis核心配置文件
- MyBatis核心配置文件的顶层结构
- environments,可以配置多个environment数据源,切换不同的数据库,比如开发的库和测试的库相互切换
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q8VaOMDW-1640340640383)(https://cdn.jsdelivr.net/gh/1wenjinjie/picture/img/202112091446550.png)]
- 类型别名(typeAliases)
<typeAliases>
<package name="com.itheima.pojo"/>
</typeAliases>
通过包扫描,取完别名后,resultType可以直接用类名//用别名可以简化配置
细节:配置各个标签需要遵循顺序
配置文件完成增删改查
- 准备环境
- 数据库tb_brand
use mybatis;
-- 删除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;
- 实体类Brand
package com.itheima.pojo;
/**
* 品牌
*
* alt + 鼠标左键:整列编辑
*
* 在实体类中,基本数据类型建议使用其对应的包装类型
*/
public class Brand {
// id 主键
private Integer id;
// 品牌名称
private String brandName;
// 企业名称
private String companyName;
// 排序字段
private Integer ordered;
// 描述信息
private String description;
// 状态:0:禁用 1:启用
private Integer status;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBrandName() {
return brandName;
}
public void setBrandName(String brandName) {
this.brandName = brandName;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public Integer getOrdered() {
return ordered;
}
public void setOrdered(Integer ordered) {
this.ordered = ordered;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
@Override
public String toString() {
return "Brand{" +
"id=" + id +
", brandName='" + brandName + '\'' +
", companyName='" + companyName + '\'' +
", ordered=" + ordered +
", description='" + description + '\'' +
", status=" + status +
'}';
}
}
- 测试用例,写到test文件下,因为是Maven工程
- 安装MyBatisX插件
MybatisX是一款基于IDEA的快速开发插件,为效率而生
主要功能:
- XML和接口方法相互跳转
- 根据接口方法生成statement
安装:
-
完成的功能列表清单:
- 查询
-
查询所有数据
-
编写接口方法:Mapper接口
参数:无
结果:List
List<Brand> selectAll();
-
编写SQL语句:SQL映射文件
<select id="selectAll" resultType="brand"> select * from tb_brand; </select>
- 执行方法测试
MyBitisTest 类,测试类
package com.itheima; import com.itheima.mapper.BrandMapper; import com.itheima.pojo.Brand; 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 org.junit.Test; import java.io.InputStream; import java.util.List; public class MyBatisTest { @Test public void testSelectAll() throws Exception { //1.加载mybitis的核心配置文件,获取sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //3.获取Mapper接口的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //4.执行方法 List<Brand> brands = brandMapper.selectAll(); System.out.println(brands); //5.释放资源 sqlSession.close(); } }
-
完成MyBatis完成操作需要几步?
三步:编写接口方法->编写SQL->执行方法
问题:上图中brandName以及companyName没有封装成功,因为mysql中字段为brand_Name,所以解决办法为:取别名
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4qpqRkmt-1640340640389)(C:\Users\wjj yes\AppData\Roaming\Typora\typora-user-images\image-20211210194807458.png)]
因为每次查询都要写一次别名,用sql片段方便写字段名。
- 除了取别名的方法,还可以用resultMap方法,也相当于取别名
- resultMap:
- 定义标签
- 在标签中,使用resultMap属性替换 resultType属性
总结:实体类属性名和数据库表列名不一致,不能自动封装数据
1.取别名:在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样,可以定义片段,提升复用性
2.resultMap:定义完成不一致的属性名和列名的映射.
- 查看详情
- 编写接口方法:Mapper接口
- 参数:id
- 结果:Brand
- 编写SQL语句:SQL映射文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4RrmTxJb-1640340640392)(https://cdn.jsdelivr.net/gh/1wenjinjie/picture/img/202112111859959.png)]
- 执行方法,测试
@Test public void testSelectById() throws Exception { int id =1; //1.加载mybitis的核心配置文件,获取sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //3.获取Mapper接口的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //4.执行方法 Brand brand = brandMapper.selectById(id); System.out.println(brand); //5.释放资源 sqlSession.close(); }
总结:
* 参数占位符: 1.#{}:会将其替换为 ? 为了防止SQL注入 2.${}:拼sql。会存在SQL注入问题 3.使用时机: 参数传递的时候:#{} 表名或者列名不固定的情况下:${}会存在sql注入 4.特殊字符处理 1.转义字符: 字符少用这个 2.COATA区:字符多的话用这个(输入CD有提示)
- 条件查询
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZKLaiEnY-1640340640395)(C:\Users\wjj yes\AppData\Roaming\Typora\typora-user-images\image-20211212210839577.png)]
第一种情况:查询散装参数
- 编写方法接口:Mapper接口
/** * *参数接收 * 1.散装参数:如果方法中有多个参数,需要使用@Param(" SQL参数占位符名称") * 2.对象参数 * 3.map集合参数 * */ 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);
- 参数:所有查询条件
<select id="selectByCondition" resultMap="brandResultMap"> select * from tb_brand where status=#{status} and company_name like #{companyName} and brand_name like #{brandName} </select>
-
结果:List
-
编写SQL语句:SQL映射文件
-
执行方法,测试
@Test public void testSelectByCondition() throws Exception { //接收参数 int status = 1; String companyName = "华为"; String brandName="华为"; //参数处理 companyName="%"+companyName+"%"; brandName="%"+brandName+"%"; //1.加载mybitis的核心配置文件,获取sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //3.获取Mapper接口的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //4.执行方法 List<Brand> brands = brandMapper.selectByCondition(status, companyName,brandName); System.out.println(brands); //5.释放资源 sqlSession.close(); }
结果:
第二种:对象参数(步骤和上面雷同)
- 接口的定义
List<Brand> selectByCondition(Brand brand);
- 测试类(因为需要返回List对象,所以需要进行参数处理后封装对象
@Test public void testSelectByCondition() throws Exception { //接收参数 int status = 1; String companyName = "华为"; String brandName="华为"; //参数处理 companyName="%"+companyName+"%"; brandName="%"+brandName+"%"; //封装对象 Brand brand=new Brand(); brand.setStatus(status); brand.setBrandName(brandName); brand.setCompanyName(companyName); //1.加载mybitis的核心配置文件,获取sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //3.获取Mapper接口的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //4.执行方法 // List<Brand> brands = brandMapper.selectByCondition(status, companyName,brandName); List<Brand> brands = brandMapper.selectByCondition(brand); System.out.println(brands); //5.释放资源 sqlSession.close(); }
第三种:map集合参数
-
@Test public void testSelectByCondition() throws Exception { //接收参数 int status = 1; String companyName = "华为"; String brandName="华为"; //参数处理 companyName="%"+companyName+"%"; brandName="%"+brandName+"%"; //封装对象 // Brand brand=new Brand(); // brand.setStatus(status); // brand.setBrandName(brandName); // brand.setCompanyName(companyName); Map map = new HashMap(); map.put("status",status); map.put("companyName",companyName); map.put("brandName",brandName); //1.加载mybitis的核心配置文件,获取sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //3.获取Mapper接口的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //4.执行方法 // List<Brand> brands = brandMapper.selectByCondition(status, companyName,brandName); //List<Brand> brands = brandMapper.selectByCondition(brand); List<Brand> brands = brandMapper.selectByCondition(map); System.out.println(brands); //5.释放资源 sqlSession.close(); }
**总结:**SQL语句设置多个参数有几种方式?
- 散装参数:需要使用@Param(“SQL中的参数占位符名称”)
- 实体类封装参数:只需要保证SQL中的参数名和实体类属性名对应上,即可设置成功
- map集合:只需要保证SQL中的参数名和map集合的键的名称对应上,即可设置成功
- 查询-多条件-动态条件查询
SQL语句会随着用户的输入或外部条件的变化而变化,我们称为动态SQL
<select id="selectByCondition"resultMap="brandResultMap"> select * from tb_brand where if(status!=null) status=#{status} and company_name like #{companyName} and brand_name like #{brandName} </select>
- MyBatis对动态SQL有很强大的支撑
- if
- choose(when,otherwise)
- trim(where,set)
- foreach
MyBatisTest.java
@Test public void testSelectByCondition() throws Exception { //接收参数 int status = 1; String companyName = "华为"; String brandName="华为"; //参数处理 companyName="%" +companyName+ "%"; brandName="%" +brandName+ "%"; //封装对象 // Brand brand=new Brand() ; // brand.setStatus(status); // brand.setBrandName(brandName); // brand.setCompanyName(companyName); Map map = new HashMap(); // map.put("status" ,status); // map.put("companyName" ,companyName); map.put("brandName" ,brandName); //1.加载mybitis的核心配置文件,获取sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //3.获取Mapper接口的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //4.执行方法 // List<Brand> brands = brandMapper.selectByCondition(status, companyName,brandName); //List<Brand> brands = brandMapper.selectByCondition(brand); List<Brand> brands = brandMapper.selectByCondition(map); System.out.println(brands); //5.释放资源 sqlSession.close(); }
BrandMapper.xml
<!-- 动态条件查询 * if:条件判断 * test: 逻辑表达式 * 问题: *恒等式 *<where>替换where 关键字 --> <select id="selectByCondition" resultMap="brandResultMap"> select * from tb_brand <where> <if test="status !=null"> and status =#{status} </if> <if test="companyName !=null "> and company_name like #{companyName} </if> <if test="brandName !=null "> and brand_name like #{brandName} </if> </where> </select>
其他文件和普通条件查询一样不变
总结:
if:用于判断参数是否有值,使用test属性进行条件判断
- 存在问题:第一个条件不需要逻辑运算符
- 解决方案
使用恒等式让所有条件个数都一样
标签替换where关键字
-
单条件-动态条件查询
从多个条件中选择一个
choose(when,otherwise):选择,类似于Java中的switch语句
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GPvDRmwu-1640340640401)(https://cdn.jsdelivr.net/gh/1wenjinjie/picture/img/202112181701020.png)]
BrandMapper.xml
<select id="selectByConditionSingle" resultMap="brandResultMap"> select * from tb_brand <where> <choose> <!-- 相当于switch--> <when test="status !=null"> <!-- 相当于case--> status =#{status} </when> <when test="companyName !=null "> <!-- 相当于case--> company_name like #{companyName} </when> <when test="brandName !=null "> <!-- 相当于case--> brand_name like #{brandName} </when> </choose> </where> </select>
MyBatisTest.java
@Test public void testSelectByConditionSingle() throws Exception { //接收参数 int status = 1; String companyName = "华为"; String brandName="华为"; //参数处理 companyName="%"+companyName+"%"; brandName="%"+brandName+ "%"; //封装对象 Brand brand=new Brand() ; brand.setStatus(status); brand.setBrandName(brandName); brand.setCompanyName(companyName); // Map map = new HashMap(); // map.put("status" ,status); // map.put("companyName" ,companyName); // map.put("brandName" ,brandName); //1.加载mybitis的核心配置文件,获取sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //3.获取Mapper接口的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //4.执行方法 // List<Brand> brands = brandMapper.selectByCondition(status, companyName,brandName); //List<Brand> brands = brandMapper.selectByCondition(brand); // List<Brand> brands = brandMapper.selectByCondition(map); List<Brand> brands = brandMapper.selectByConditionSingle(brand); System.out.println(brands); //5.释放资源 sqlSession.close(); }
- 添加
- 编写接口方法:Mapper接口
void add(Brand brand);
- 参数:除了id之外的所有数据
- 结果:void
- 编
- 写SQL语句:SQL映射文件
@Test public void testAdd() throws Exception { //接收参数 int status = 1; String companyName = "波导手机"; String brandName="波导"; String description = "手机中的战斗机"; int order =100; //封装对象 Brand brand=new Brand() ; brand.setStatus(status); brand.setBrandName(brandName); brand.setCompanyName(companyName); brand.setDescription(description); brand.setOrdered(order); // Map map = new HashMap(); // map.put("status" ,status); // map.put("companyName" ,companyName); // map.put("brandName" ,brandName); //1.加载mybitis的核心配置文件,获取sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //3.获取Mapper接口的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //4.执行方法 brandMapper.add(brand); //提交事务 sqlSession.commit(); //5.释放资源 sqlSession.close(); }
若不行手动提交事务,可以选择自动提交
将sqlSession改为true
- 添加-主键返回
在数据添加成功后,需要获取插入数据库数据的主键值
比如:添加订单和订单项
返回添加数据的主键 1.useGenerateKeys 2.KeyProperty
<insert id="add" useGeneratedKeys="true" keyProperty="id"> insert into tb_brand(brand_name, company_name, ordered, description, status) values(#{brandName},#{companyName},#{ordered},#{description},#{status}); </insert>
- 修改
- 修改全部字段
@Test public void testUpdate() throws Exception { //接收参数 int status = 1; String companyName = "波导手机"; String brandName="波导"; String description = "波导手机,手机中的战斗机"; int order =200; int id= 5; //封装对象 Brand brand=new Brand() ; brand.setStatus(status); brand.setBrandName(brandName); brand.setCompanyName(companyName); brand.setDescription(description); brand.setOrdered(order); brand.setId(id); // Map map = new HashMap(); // map.put("status" ,status); // map.put("companyName" ,companyName); // map.put("brandName" ,brandName); //1.加载mybitis的核心配置文件,获取sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象 //SqlSession sqlSession = sqlSessionFactory.openSession(); SqlSession sqlSession = sqlSessionFactory.openSession(); //3.获取Mapper接口的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //4.执行方法 int update = brandMapper.update(brand); System.out.println(update); //提交事务 sqlSession.commit(); //5.释放资源 sqlSession.close(); }
- 修改动态字段
动态修改就是只修改一些值,不修改全部值。具体和全部修改方法类似,只是sql语句变化
<update id="update"> update tb_brand <set> <if test="brandName !=null and brand_name !=' ' "> brand_name =#{brandName}, </if> <if test="companyName !=null and companyName !=' ' "> company_name=#{companyName}, </if> <if test="ordered !=null"> ordered=#{ordered}, </if> <if test=" description !=null and description !=' ' "> description=#{description}, </if> <if test="status !=null "> status=#{status} </if> </set> where id =#{id}; </update>
- 删除
- 删除一个
@Test public void deleteById() throws Exception { //接收参数 int id= 4; //1.加载mybitis的核心配置文件,获取sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象 //SqlSession sqlSession = sqlSessionFactory.openSession(); SqlSession sqlSession = sqlSessionFactory.openSession(); //3.获取Mapper接口的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //4.执行方法 brandMapper.deleteById(id); //提交事务 sqlSession.commit(); //5.释放资源 sqlSession.close(); }
结果:第4条数据没了
- 批量删除
- 编写接口方法
- 编写SQL映射文件
注意:mybatis会将数组参数封装为一个map集合,使用@Param注解改变map集合的默认key的名称
@Test
public void deleteByIds() throws Exception {
//接收参数
int [] ids={1,2,3};
//1.加载mybitis的核心配置文件,获取sqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.获取SqlSession对象
//SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//3.获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4.执行方法
brandMapper.deleteByIds(ids);
//提交事务
sqlSession.commit();
//5.释放资源
sqlSession.close();
}
结果:1,2,3数据被删除
参数传递
MyBatis接口方法1中可以接收各种各样的参数,MyBatis底层对于这些参数进行不同的封装处理方式
- 单个参数:
- POJO类型:
- Map集合:
- Collection:
- List:
- Array:
- 其他类型
- 多个参数:
用这个例子说明底层分装是Map集合
查询User表中username为zhangsan,password为123的信息
- 在UserMapper.java文件中添加
User select(@Param("username") String username, @Param("password") String password);
- 写sql语句
<select id="select" resultType="user">
select *
from tb_user
where
username =#{username}
and password =#{password}
</select>
- 创建一个执行类,大部分代码是类似的,不需要修改
@Test
public void testSelect() throws Exception {
//接收参数
//1.加载mybitis的核心配置文件,获取sqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.获取SqlSession对象
//SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//3.获取Mapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//4.执行方法
String username="zhangsan"; //写的
String password="123"; //写的
User user = userMapper.select(username,password); //写的
System.out.println(user); //写的
//提交事务
sqlSession.commit();
//5.释放资源
sqlSession.close();
}
通过debug方式查看mybatis底层如何封装数据,如果没用@Param,那么Map集合封装键值对是如下,如果使用@Param注解可以将主键修改成数据名字,替换成Map集合默认arg的键名,方便查看。
* 多个参数:封装为Map集合
* map.put("arg0",参数值1)
* map.put("param1",参数值1)
* map.put("arg1",参数值2)
* map.put("param2",参数值2)
*
/*
用@Param注解,替换Map集合中默认的arg键名
* 单个参数:
1. POJO类型:直接使用,属性名和参数占位符名称一致
2. Map集合:直接使用,键名和参数占位符名称一致
3. Collection:封装为Map集合
* map.put("arg0",collection集合)
* map.put("collection",collection集合)
*
4. List:封装为Map集合
* map.put("arg0",list集合)
* map.put("collection",list集合)
* map.put("list",list集合)
*
5. Array:
* map.put("arg0",Array数组)
* map.put("array",Array数组)
*
6. 其他类型:直接使用
* 多个参数:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
* map.put("arg0",参数值1)
* map.put("param1",参数值1)
* map.put("arg1",参数值2)
* map.put("param2",参数值2)
*/
结论:无论如何 用@Param注解,替换Map集合中默认的arg键名
注解开发
区别:配置文件完成增删改查就是将sql语句写入配置文件,而注解开发技术将sql语句写到注解中。
演示select的注解开发
@Select("select * from tb_user where id = #{id}")