个人总结:
mybatis的增删改查操作 就是通过测试程序接收的用户信息 然后通过接口的抽象方法传递给sql的映射文件当中进行。SQL语句的查操作的时候,查出来的数据是以对象的形式封装返回(而且要注意:数据库中的字段名和对象属性名要一致,要不然返回给对象的属性值会为null, 如果不一致就用resultMap标签 干成一致就可了)
而且通过接口当中的抽象方法定义SQL语句应该返回的类型是List还是单纯的一个对象返回,因为毕竟程序测试调用的是该抽象方法
再次强调(总体思路):
当进行查询操作的时候:sql映射文件通过接收接口拿到的用户输入的查询数据,进行执行SQL语句 (这里要注意:#{占位符} 占位符一定要和对象的属性名一样, 因为用户输入的数据是封装到了对象的属性当中了,我们只有通过属性名拿到用户输入的数据,不一样的话当然拿不到了) 通过SQL语句查询的结果是以封装对象的形式返回的,封装对象是封装到对象的属性当中,所以这里一定要保证数据库表中的字段名和对象的属性名一样,不一样查询出来的数据肯定封装不到对象的属性当中啊,如果不一样对象中属性名和字段名不一样的就会返回给用户null了, 因为就没有为该属性名赋上值, 所以一定要用ResultMap方法 把字段名和属性名搞成一样
[就比如数据库的company_name字段 在Brand对象当中的对应属性是 companyNam 二个名字就不一样 怎么能把查询出来的数据封装到对象的companyNam属性当中呢? 所以要一样]
当返回的结果有null值或者空值的时候,首先要考虑的是看看数据库表的字段名和对象的属性名是否一样!
第一步: 环境准备
1、数据库表 tb_brand 表准备:2
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);
2、实体类准备
package com.itheima.pojo;
public class Brand {
/**
* 这里要注意 属性名对应的数据库名不相同
* JDBC当中不相同也能查出来数据 是因为JDBC当中是先把数据库数据筛选出来后
* 通过名字 setting到对象的属性当中统一把对象存放到集合的 所以可以不相同
* 但是这里不相同的话 要处理一下,要不然属性名和数据库名不同的为null
*/
// id 主键
private Integer id;
// 品牌名称
private String brandName;
// 企业名称
private String companyNam;
// 排序字段
private Integer ordered;
// 描述信息
private String description;
// 状态: 0:禁用 1:启动
private Integer status; // 这里int类型我们尽量用包装类型 因为int类型当我们这个属性不赋值的时候
// 默认值为0 而我们业务中 0 :代表禁用(会给我们的业务带来疑惑)
// getter and setter 方法
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 getCompanyNam() {
return companyNam;
}
public void setCompanyNam(String companyNam) {
this.companyNam = companyNam;
}
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;
}
// toString 方法
@Override
public String toString() {
return "Brand{" +
"id=" + id +
", brandName='" + brandName + '\'' +
", companyNam='" + companyNam + '\'' +
", ordered=" + ordered +
", description='" + description + '\'' +
", status=" + status +
'}';
}
}
3、测试用例:
也就是测试代码的、Maven工程当中test包下是测试用的 (下列演示:假设在com.itheima.test包下的MyBatisTest类当中测试)
package com.itheima.test;
import com.itheima.pojo.Brand;
import com.itheima.pojo.mapper.BrandMapper;
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.IOException;
import java.io.InputStream;
import java.util.List;
/**
* 测试代码的程序
*/
public class MyBatisTest {
@Test
/**
* 测试方法
*/
public void testSelectAll() throws IOException {
// 1、 加载核心配置文件,获取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、获取Mapper接口的代理对象 (解决硬编码问题)
BrandMapper brandMapper =sqlSession.getMapper(BrandMapper.class);
// 4、执行方法
List<Brand> brands =brandMapper.selectAll();
System.out.println(brands);
// 5、释放资源
sqlSession.close();
}
}
注意啊:这个加载核心配置文件路径:是从resource包名路径开始的:
4、安装MyBatisX插件
MyBatisX插件就是解决 在开发中我们的SQL映射文件中的id 和 resultType(返回类型) 需要对应着 SQL映射文件接口的抽象方法和返回类型 (也就是Mapper代理开发 解决了硬编码问题)
MyBatisX插件解决了两个问题:
1、SQL映射文件(UserMapper.xml)和 SQL映射文件接口 (UserMapper) id需要对应着接口的抽象方法名 返回类型需要对应着接口的抽象方法返回的类型,那么在开发中我们需要两个文件来回查看点击, 该插件很好的解决了这个问题,具体解决样式如下操作
2、当我们安装好该插件后,假如我们在SQL映射文件接口当中写了一个抽象方法,但是这个方法的方法名和返回类型在SQL映射文件当中不存在,那么我们就可以利用该插件快速导入SQL映射文件的statement,然后我们就可以写SQL语句了~
2、假设我们现在在接口中写的抽象方法 在SQL映射文件中不对应id 和 返回类型 查看该插件带来的好处如下
我们直接在红线上 ALT + 回车 直接就帮我们导入到SQL映射文件啦~
接下来开始操作 查操作
第一种查询:查看所有数据
Brand封装数据对象的类和数据库数据写好之后:
开始配置SQL映射文件 和 SQL 映射文件接口(代理开发Mapper 该接口就是为了解决硬编码问题)
3、写好之后 执行方法 进行测试test:
注意这里测试的时候看看mybites的核心配置文件的加载sql映射文件 和 数据库的连接地址是否都修改了,数据库连接地址要是该项目中所用到的表的数据库名,又因为这个是对Brand类型的表进行操作的所以要加载映射文件是查看tb_brand的表的配置文件
代码测试:
注意:上面的输出结果为什么brandName companyNam 在数据库当中有数据 但查询结果为null 呢? (因为SQL语句查询的结果 会通过数据库字段返回给Brand对象的属性名 进行封装返回 名字对应不上 当然该字段的数据就封装不上了)
这里要注意: 这里的属性名必须和数据库中的名字相同
JDBC当中 是把数据库当中的数据一个一个拿出来通过setting方法
存放到对象属性当中的, 所以属性名可以采用驼峰命名法 可以和数据库
的名字不一样 因为毕竟是通过setting方法一个一个赋值到对象属性的
而mybatis当中封装数据库数据的对象属性名为brandName....和数据库的字段名brand_name.... 并且不是通过setting方法赋值存放到属性的 所以要用下列两种方法操作才能输出数据库当中的数据~
第一种解决办法(有缺点):在SQL映射文件当中起别名:(把别名起的和Brand对象类当中的属性名一样即可 数据库字段名和Brand类的属性名一样的就不用起别名了)
再次测试输出结果:
第二种解决办法:resultMap (常用方法)
<?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:名称空间
id="" 引号里面是唯一的 用过之后就要用其他的了 所以需要用到Mapper代理开发
-->
<mapper namespace="com.itheima.pojo.mapper.BrandMapper">
<!-- resultMap 方法:
1、定义<resultMap> 标签 (其中 id 值 随便写、 type 变成了SQL语句返回类型Brand对象)
2、使用resultMap属性 替换了 resultType属性
-->
<resultMap id="brandResultMap" type="com.itheima.pojo.Brand">
<!--
id: 完成主键的映射(就是数据库id字段和实体类Brand的属性名不同 然后通过column和property分别表示出来即可得到结果)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
result: 完成一般字段的映射(就是除了id其他的字段)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
在此项目中 是数据库中字段 brand_name 和 company_name 和实体类属性名不同 不包括id字段
所以下列的操作是对一般字段的映射
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyNam" />
</resultMap>
<select id="selectAll" resultMap="brandResultMap">
select *from tb_brand;
</select>
</mapper>
第二种查询:查看详情
这里有个面试问题:
* 参数占位符:
1、 #{} : 会将其SQL语句替换为 ? 目的:防止SQL注入 (Preparing: select * from tb_brand where id =?; )
2、${} : 拼sql , 会存在sql注入问题 ( Preparing: select * from tb_brand where id =1; )
3、使用时机:
* 参数传递的时候:#{}
* 表名或者列名不固定的情况下:${} 会存在SQL注入问题
* 参数类型: parameterType:可省略 因为接口当中已经把id设置为int型了 所以这里#{id} 默认就是传过来的int型1
接口中设置查看详情抽象方法:
SQL映射文件:
#{id}的时候SQL字符格式如下:
${id}的时候SQL字段格式如下:
核心配置文件:
测试:(这里BrandMapper接口调用的是查询详情的方法)
测试结果:
注意使用小于号的时候这里的SQL语句:
解决方法:
第一种:转义字符
第二种:CDATA区
第三种查询:条件查询(重点)【模糊查询】
第一种:散装参数:
Mapper接口:
package com.itheima.pojo.mapper;
import com.itheima.pojo.Brand;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface BrandMapper {
/**
* 查询所有数据
*/
List<Brand> selectAll();
/**
* 查看详情: 根据ID查询 (就是比如用户想要查询id为1的一条数据信息)
*
* 因为数据都封装到Brand对象属性当中了、 所以一条信息返回Brand对象类型即可,
* 上面返回的List<Brand>格式 是因为查询了所有的数据库当中的数据
* 接收一个用户输入的id
*
* 解释一下参数的传递过程:
* 测试程序当中 Brand brand =brandMapper.selectById(id);
* 把id传入到该接口抽象方法当中,然后又因为该抽象方法名是SQL映射文件当中的id唯一标识名,
* 所以把这个id传递给了SQL语句进行查询处理 (注意这里SQL语句 #{id}和 ${id} 对SQL处理结果不一样)
* 然后返回类型是Brand对象 以Brand对象封装数据返回
*
*/
Brand selectById(int id);
/**
* 条件查询
* * 参数接收
* 1、散装参数: 如果方法中有多个参数,需要使用@Param("SQL参数占位符名称") #{} 括号里面就是参数占位符
* (因为当多个参数的时候 不知道哪个参数对应SQL语句哪个字段)
* 2、对象参数
* 3、map集合参数
*
*/
// 散装参数
List<Brand> selectByCondition
(@Param("status") int status,@Param("companyNam") String companyNam,@Param("brandName") String brandName);
}
BrandMapper.xml SQL映射文件:
注意啊:这里的select * from tb_brand
where status =#{status} and company_name like #{companyNam} and brand_name like #{brandName}; SQL语句当中 #{status}..... 是参数占位符, 这个占位符一定要和代理开发接口中方法的参数相同,因为代理开发接口方法接收了用户输入的参数, 通过这个方法进入SQL语句一定要把方法中的参数和SQL语句中的占位符保持一致,要不然不知道传给谁
<?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:名称空间
id="" 引号里面是唯一的 用过之后就要用其他的了 所以需要用到Mapper代理开发
-->
<mapper namespace="com.itheima.pojo.mapper.BrandMapper">
<!-- resultMap 方法:
1、定义<resultMap> 标签 (其中 id 值 随便写、 type 变成了SQL语句返回类型Brand对象)
2、使用resultMap属性 替换了 resultType属性
-->
<resultMap id="brandResultMap" type="com.itheima.pojo.Brand">
<!--
id: 完成主键的映射(就是数据库id字段和实体类Brand的属性名不同 然后通过column和property分别表示出来即可得到结果)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
result: 完成一般字段的映射(就是除了id其他的字段)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
在此项目中 是数据库中字段 brand_name 和 company_name 和实体类属性名不同 不包括id字段
所以下列的操作是对一般字段的映射
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyNam" />
</resultMap>
<select id="selectAll" resultMap="brandResultMap">
select *from tb_brand;
</select>
<!--
* 参数占位符:
1、 #{} : 会将其SQL语句替换为 ? 目的:防止SQL注入 (Preparing: select * from tb_brand where id =?; )
2、${} : 拼sql , 会存在sql注入问题 ( Preparing: select * from tb_brand where id =1; )
3、使用时机:
* 参数传递的时候:#{}
* 表名或者列名不固定的情况下:${} 会存在SQL注入问题
* 参数类型: parameterType:可省略 因为接口当中已经把id设置为int型了 所以这里#{id} 默认就是传过来的int型1
-->
<!--
注意SQL语句: 有时候我们会用到 > 、 < 、 = .....
但是在这里面 < (小于号) 是会报错的 因为 <号 和select标签 <select 重了
解决方法二:CDATA区
-->
<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 #{companyNam} and brand_name like #{brandName};
</select>
</mapper>
mybatis核心配置文件:
代码测试:
输出结果(模糊查询的结果):
第二种: 封装对象:
BrandMapper 接口:
package com.itheima.pojo.mapper;
import com.itheima.pojo.Brand;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface BrandMapper {
/**
* 查询所有数据
*/
List<Brand> selectAll();
/**
* 查看详情: 根据ID查询 (就是比如用户想要查询id为1的一条数据信息)
*
* 因为数据都封装到Brand对象属性当中了、 所以一条信息返回Brand对象类型即可,
* 上面返回的List<Brand>格式 是因为查询了所有的数据库当中的数据
* 接收一个用户输入的id
*
* 解释一下参数的传递过程:个人认为
* 测试程序当中 Brand brand =brandMapper.selectById(id);
* 把id传入到该接口抽象方法当中,然后又因为该抽象方法名是SQL映射文件当中的id唯一标识名,
* 所以把这个id传递给了SQL语句进行查询处理 (注意这里SQL语句 #{id}和 ${id} 对SQL处理结果不一样)
* 然后返回类型是Brand对象 以Brand对象封装数据返回
*
* 单个参数的时候就不用使用@Param标注了,因为就一个参数,传给SQL映射文件的时候,sql语句肯定
* 知道接收的就是这一个参数 能对应到sql语句中 但多个参数的时候,sql语句就分不清哪个传给哪
* 个了
*
*/
Brand selectById(int id);
/**
* 条件查询
* * 参数接收(三种方式)
* 1、散装参数: 如果方法中有多个参数,需要使用@Param("SQL参数占位符名称") SQL映射文件中的 #{} 括号里面就是参数占位符
* (因为当多个参数的时候 不知道哪个参数对应SQL语句哪个字段)
* 2、对象参数
* 3、map集合参数
*
*/
// 对象参数
List<Brand> selectByCondition(Brand brand);
}
sql映射文件.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:名称空间
id="" 引号里面是唯一的 用过之后就要用其他的了 所以需要用到Mapper代理开发
-->
<mapper namespace="com.itheima.pojo.mapper.BrandMapper">
<!-- resultMap 方法:
1、定义<resultMap> 标签 (其中 id 值 随便写、 type 变成了SQL语句返回类型Brand对象)
2、使用resultMap属性 替换了 resultType属性
-->
<resultMap id="brandResultMap" type="com.itheima.pojo.Brand">
<!--
id: 完成主键的映射(就是数据库id字段和实体类Brand的属性名不同 然后通过column和property分别表示出来即可得到结果)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
result: 完成一般字段的映射(就是除了id其他的字段)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
在此项目中 是数据库中字段 brand_name 和 company_name 和实体类属性名不同 不包括id字段
所以下列的操作是对一般字段的映射
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyNam" />
</resultMap>
<select id="selectAll" resultMap="brandResultMap">
select *from tb_brand;
</select>
<!--
* 参数占位符:
1、 #{} : 会将其SQL语句替换为 ? 目的:防止SQL注入 (Preparing: select * from tb_brand where id =?; )
2、${} : 拼sql , 会存在sql注入问题 ( Preparing: select * from tb_brand where id =1; )
3、使用时机:
* 参数传递的时候:#{}
* 表名或者列名不固定的情况下:${} 会存在SQL注入问题
* 参数类型: parameterType:可省略 因为接口当中已经把id设置为int型了 所以这里#{id} 默认就是传过来的int型1
-->
<!--
注意SQL语句: 有时候我们会用到 > 、 < 、 = .....
但是在这里面 < (小于号) 是会报错的 因为 <号 和select标签 <select 重了
解决方法二:CDATA区
-->
<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 #{companyNam} and brand_name like #{brandName};
</select>
</mapper>
测试程序:
package com.itheima.test;
import com.itheima.pojo.Brand;
import com.itheima.pojo.mapper.BrandMapper;
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.IOException;
import java.io.InputStream;
import java.util.List;
/**
* 测试代码的程序
*/
public class MyBatisTest {
@Test
/**
* 测试方法
*/
public void testSelectByCondition() throws IOException {
// 用户接收参数 (散装参数)
int status = 1;
String companyNam = "华为";
String brandName = "华为";
// 处理一下用户输入的参数
companyNam = "%" + companyNam + "%"; // 注意一般我们在这里进行SQL语句模糊查询拼接 :%华为%
brandName = "%" + brandName + "%";
// 把散装参数封装成对象
Brand brand = new Brand();
brand.setStatus(status);
brand.setCompanyNam(companyNam);
brand.setBrandName(brandName);
// 1、 加载核心配置文件,获取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、获取Mapper接口的代理对象 (解决硬编码问题)
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
// 4、执行方法
List<Brand> brands = brandMapper.selectByCondition(brand);
System.out.println(brands);
// 5、释放资源
sqlSession.close();
}
}
输出结果:
第三种:Map集合参数:
接口:
package com.itheima.pojo.mapper;
import com.itheima.pojo.Brand;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
public interface BrandMapper {
/**
* 查询所有数据
*/
List<Brand> selectAll();
/**
* 查看详情: 根据ID查询 (就是比如用户想要查询id为1的一条数据信息)
*
* 因为数据都封装到Brand对象属性当中了、 所以一条信息返回Brand对象类型即可,
* 上面返回的List<Brand>格式 是因为查询了所有的数据库当中的数据
* 接收一个用户输入的id
*
* 解释一下参数的传递过程:个人认为
* 测试程序当中 Brand brand =brandMapper.selectById(id);
* 把id传入到该接口抽象方法当中,然后又因为该抽象方法名是SQL映射文件当中的id唯一标识名,
* 所以把这个id传递给了SQL语句进行查询处理 (注意这里SQL语句 #{id}和 ${id} 对SQL处理结果不一样)
* 然后返回类型是Brand对象 以Brand对象封装数据返回
*
*/
Brand selectById(int id);
/**
* 条件查询
* * 参数接收(三种方式)
* 1、散装参数: 如果方法中有多个参数,需要使用@Param("SQL参数占位符名称") #{} 括号里面就是参数占位符
* (因为当多个参数的时候 不知道哪个参数对应SQL语句哪个字段)
* 2、对象参数
* 3、map集合参数
*
*/
// Map集合参数
List<Brand> selectByCondition(Map map);
}
sql映射文件.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:名称空间
id="" 引号里面是唯一的 用过之后就要用其他的了 所以需要用到Mapper代理开发
-->
<mapper namespace="com.itheima.pojo.mapper.BrandMapper">
<!-- resultMap 方法:
1、定义<resultMap> 标签 (其中 id 值 随便写、 type 变成了SQL语句返回类型Brand对象)
2、使用resultMap属性 替换了 resultType属性
-->
<resultMap id="brandResultMap" type="com.itheima.pojo.Brand">
<!--
id: 完成主键的映射(就是数据库id字段和实体类Brand的属性名不同 然后通过column和property分别表示出来即可得到结果)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
result: 完成一般字段的映射(就是除了id其他的字段)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
在此项目中 是数据库中字段 brand_name 和 company_name 和实体类属性名不同 不包括id字段
所以下列的操作是对一般字段的映射
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyNam" />
</resultMap>
<select id="selectAll" resultMap="brandResultMap">
select *from tb_brand;
</select>
<!--
* 参数占位符:
1、 #{} : 会将其SQL语句替换为 ? 目的:防止SQL注入 (Preparing: select * from tb_brand where id =?; )
2、${} : 拼sql , 会存在sql注入问题 ( Preparing: select * from tb_brand where id =1; )
3、使用时机:
* 参数传递的时候:#{}
* 表名或者列名不固定的情况下:${} 会存在SQL注入问题
* 参数类型: parameterType:可省略 因为接口当中已经把id设置为int型了 所以这里#{id} 默认就是传过来的int型1
-->
<!--
注意SQL语句: 有时候我们会用到 > 、 < 、 = .....
但是在这里面 < (小于号) 是会报错的 因为 <号 和select标签 <select 重了
解决方法二:CDATA区
-->
<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 #{companyNam} and brand_name like #{brandName};
</select>
</mapper>
程序测试:
package com.itheima.test;
import com.itheima.pojo.Brand;
import com.itheima.pojo.mapper.BrandMapper;
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.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 测试代码的程序
*/
public class MyBatisTest {
@Test
/**
* 测试方法
*/
public void testSelectByCondition() throws IOException {
// 用户接收参数 (散装参数)
int status = 1;
String companyNam = "华为";
String brandName = "华为";
// 处理一下用户输入的参数
companyNam = "%" + companyNam + "%"; // 注意一般我们在这里进行SQL语句模糊查询拼接 :%华为%
brandName = "%" + brandName + "%";
// 把散装参数封装成Map
Map map =new HashMap();
map.put("status",status); // 注意这里的key要和SQL映射文件当中的SQL参数占位符一样 #{status}
map.put("companyNam",companyNam); // 意思就是为这个参数占位符 赋上后面的status(接收的用户信息)
map.put("brandName",brandName);
// 1、 加载核心配置文件,获取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、获取Mapper接口的代理对象 (解决硬编码问题)
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
// 4、执行方法
List<Brand> brands = brandMapper.selectByCondition(map);
System.out.println(brands);
// 5、释放资源
sqlSession.close();
}
}
输出结果:
第四种: 多条件的动态条件查询(第三种的优化)
补充细节1: 动态查询的时候最好把 "where" 写成标签形式 这样会让Mybatis帮我们处理SQL语句中的小问题
补充细节2:test标签属性当中:判断的是接收用户输入进来的数据是否为空或者空串,这个数据就是接口中的参数,因为接口中的参数是来自测试程序用户传过来的参数, 接口中的参数最终会进入到sql映射文件当中的#{占位符}占位符当中,让其跑SQL语句, 所以我们test后面判断占位符即可 、因为毕竟SQL语句是用户输入过来的数据,用户输入过来的数据和占位符必须保持一样 要不然就不是用户输入进来的数据了
BrandMapper 接口:
package com.itheima.pojo.mapper;
import com.itheima.pojo.Brand;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
public interface BrandMapper {
/**
* 查询所有数据
*/
List<Brand> selectAll();
/**
* 查看详情: 根据ID查询 (就是比如用户想要查询id为1的一条数据信息)
*
* 因为数据都封装到Brand对象属性当中了、 所以一条信息返回Brand对象类型即可,
* 上面返回的List<Brand>格式 是因为查询了所有的数据库当中的数据
* 接收一个用户输入的id
*
* 解释一下参数的传递过程:个人认为
* 测试程序当中 Brand brand =brandMapper.selectById(id);
* 把id传入到该接口抽象方法当中,然后又因为该抽象方法名是SQL映射文件当中的id唯一标识名,
* 所以把这个id传递给了SQL语句进行查询处理 (注意这里SQL语句 #{id}和 ${id} 对SQL处理结果不一样)
* 然后返回类型是Brand对象 以Brand对象封装数据返回
*
*/
/**
* 条件查询
* * 参数接收(三种方式)
* 1、散装参数: 如果方法中有多个参数,需要使用@Param("SQL参数占位符名称") #{} 括号里面就是参数占位符
* (因为当多个参数的时候 不知道哪个参数对应SQL语句哪个字段)
* 2、对象参数
* 3、map集合参数
*
*/
// Map集合参数
List<Brand> selectByCondition(Map map);
}
sql映射文件.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:名称空间
id="" 引号里面是唯一的 用过之后就要用其他的了 所以需要用到Mapper代理开发
-->
<mapper namespace="com.itheima.pojo.mapper.BrandMapper">
<!-- resultMap 方法:
1、定义<resultMap> 标签 (其中 id 值 随便写、 type 变成了SQL语句返回类型Brand对象)
2、使用resultMap属性 替换了 resultType属性
-->
<resultMap id="brandResultMap" type="com.itheima.pojo.Brand">
<!--
id: 完成主键的映射(就是数据库id字段和实体类Brand的属性名不同 然后通过column和property分别表示出来即可得到结果)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
result: 完成一般字段的映射(就是除了id其他的字段)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
在此项目中 是数据库中字段 brand_name 和 company_name 和实体类属性名不同 不包括id字段
所以下列的操作是对一般字段的映射
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyNam" />
</resultMap>
<select id="selectAll" resultMap="brandResultMap">
select *from tb_brand;
</select>
<!--
动态条件查询
test 里面 也就是说判断用户传过来的数据是否为空和空串(注意不带空格) 是的话就不执行这句if标签 开始判断下一个if标签
最后只要有一个if标签中的条件是接收的用户信息的数据 那么就会 "select *....." 把关于该条信息的数据返回给用户(模糊查询)
记住: 动态查询也就是说,if如果不成立的话这个if里面的SQL语句就不跑了,比如三个都成立的时候 SQL语句是:select * from tb_brand where status =? and company_name like ? and brand_name like ? ; 最终的数据结果也就是这个SQL语句查询的结果
但是如果比如第一个if(status 为null了)的不成立:那么SQL语句就是:select * from tb_brand WHERE company_name like ? and brand_name like ? ; 最终的数据结果也就是这个SQL语句查询的结果
-->
<select id="selectByCondition" resultMap="brandResultMap">
select * from tb_brand
where
<if test="status != null"> status =#{status} </if>
<if test="companyNam !=null and companyNam !='' ">
and company_name like #{companyNam}
</if>
<if test="brandName !=null and brandName !='' ">
and brand_name like #{brandName}
</if>
</select>
</mapper>
程序测试:
package com.itheima.test;
import com.itheima.pojo.Brand;
import com.itheima.pojo.mapper.BrandMapper;
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.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 测试代码的程序
*/
public class MyBatisTest {
@Test
/**
* 测试方法
*/
public void testSelectByCondition() throws IOException {
// 接收用户信息 ( 假设这里我们动态接收2个信息 )
int status = 1;
String companyNam = "华为";
// String brandName = "华为";
// 处理一下用户输入的参数
companyNam = "%" + companyNam + "%"; // 注意一般我们在这里进行SQL语句模糊查询拼接 :%华为%
// brandName = "%" + brandName + "%";
// 把散装参数封装成Map
Map map =new HashMap();
map.put("status",status); // 注意这里的key要和SQL映射文件当中的SQL参数占位符一样 #{status}
map.put("companyNam",companyNam); // 意思就是为这个参数占位符 赋上后面的status(接收的用户信息)
// map.put("brandName",brandName);
// 1、 加载核心配置文件,获取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、获取Mapper接口的代理对象 (解决硬编码问题)
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
// 4、执行方法
List<Brand> brands = brandMapper.selectByCondition(map);
System.out.println(brands);
// 5、释放资源
sqlSession.close();
}
}
结果:
但是仍然有点小问题: 演示如下:
对应的sql映射文件的SQL语句:
测试结果:(会发现第一个条件不成立的时候 第二个条件的sql语句成第一个了 但是有and 所以报错 有问题了)
解决上述问题:两种方案
第一种:1=1 形式
第二种:Mybatis自带的where标签: 就能解决上述问题:
第五种查询:单条件的动态条件查询:
单条件动态查询:就是用户在几个条件当中只选择了一个条件然乎对其进行模糊查询 (超过一个条件的话就用多条件的动态条件查询了)
注意: 认真看下面的图片 看看条件是什么(就是数据库字段的名字呗,比如公司名字,公司状态等....)
接口:
package com.itheima.pojo.mapper;
import com.itheima.pojo.Brand;
import java.util.List;
public interface BrandMapper {
/**
* 单条件动态查询
* 用一个Brand对象接收用户输入的信息即可
*/
List<Brand> selectByConditionSingle(Brand brand);
}
sql映射文件.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:名称空间
id="" 引号里面是唯一的 用过之后就要用其他的了 所以需要用到Mapper代理开发
-->
<mapper namespace="com.itheima.pojo.mapper.BrandMapper">
<!-- resultMap 方法:
1、定义<resultMap> 标签 (其中 id 值 随便写、 type 变成了SQL语句返回类型Brand对象)
2、使用resultMap属性 替换了 resultType属性
-->
<resultMap id="brandResultMap" type="com.itheima.pojo.Brand">
<!--
id: 完成主键的映射(就是数据库id字段和实体类Brand的属性名不同 然后通过column和property分别表示出来即可得到结果)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
result: 完成一般字段的映射(就是除了id其他的字段)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
在此项目中 是数据库中字段 brand_name 和 company_name 和实体类属性名不同 不包括id字段
所以下列的操作是对一般字段的映射
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyNam" />
</resultMap>
<select id="selectAll" resultMap="brandResultMap">
select *from tb_brand;
</select>
<!--
动态条件查询
test 里面 也就是说判断用户传过来的数据是否为空和空串(注意不带空格) 是的话就不执行这句if标签 开始判断下一个if标签
最后只要有一个if标签中的条件是接收的用户信息的数据 那么就会 "select *....." 把关于该条信息的数据返回给用户(模糊查询)
-->
<select id="selectByCondition" resultMap="brandResultMap">
select * from tb_brand
<where>
<if test="status != null"> status =#{status} </if>
<if test="companyNam !=null and companyNam !='' ">
and company_name like #{companyNam}
</if>
<if test="brandName !=null and brandName !='' ">
and brand_name like #{brandName}
</if>
</where>
</select>
<!-- 单条件动态查询 -->
<select id="selectByConditionSingle" resultMap="brandResultMap">
select * from tb_brand
where
<choose> <!-- 相当于java的switch -->
<when test="status != null" > status =#{status} </when> <!-- when 相当于 case 因为是单条件查询 所以不用and 哪个when成立就用哪个sql语句 -->
<when test="companyNam !=null and companyNam !='' "> company_name like #{companyNam} </when>
<when test="brandName !=null and brandName !='' "> brand_name like #{brandName} </when>
</choose>
</select>
</mapper>
程序测试:
package com.itheima.test;
import com.itheima.pojo.Brand;
import com.itheima.pojo.mapper.BrandMapper;
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.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 测试代码的程序
*/
public class MyBatisTest {
@Test
/**
* 测试方法
*/
public void testSelectByCondition() throws IOException {
// 接收用户信息
/**
* 这里我们模拟接收单条件动态查询
* 用户只输入进来一个条件
* 模拟查询
*/
String companyNam = "华为";
// 处理一下用户输入的参数
companyNam = "%" + companyNam + "%"; // 注意一般我们在这里进行SQL语句模糊查询拼接 :%华为%
// 把散装参数封装成Brand对象 单条件查询
Brand brand =new Brand();
brand.setCompanyNam(companyNam);
// 1、 加载核心配置文件,获取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、获取Mapper接口的代理对象 (解决硬编码问题)
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
// 4、执行方法
List<Brand> brands = brandMapper.selectByConditionSingle(brand);
System.out.println(brands);
// 5、释放资源
sqlSession.close();
}
}
结果:
但是也会有问题: 就是当用户一个都不选条件的时候:相当于传了一个空对象
解决方法: 用<where>标签 让mybatis帮我们处理:
二、添加操作
第一种添加方式:
细节:接收用户除了id之外的所有添加信息(这里id不用让用户自己添加,因为我们在数据库当中已经设置成了自动增长的形式了主键id了)
测试测序:
package com.itheima.test;
import com.itheima.pojo.Brand;
import com.itheima.pojo.mapper.BrandMapper;
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.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 测试代码的程序
*/
public class MyBatisTest {
@Test
/**
* 测试方法
* 模拟用户添加操作 (除了id之外所有的数据)
* 封装成对象的形式
*/
public void testAdd() throws IOException {
// 接收参数
int status =1;
String companyNam ="波导手机";
String brandName ="波导";
String description ="手机中的战斗机";
int ordered =100;
// 封装对象
Brand brand =new Brand();
brand.setStatus(status);
brand.setBrandName(brandName);
brand.setCompanyNam(companyNam);
brand.setDescription(description);
brand.setOrdered(ordered);
// 1、 加载核心配置文件,获取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、获取Mapper接口的代理对象 (解决硬编码问题)
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
// 4、执行方法
/**
* 注意: add方法 的返回类型为void 也就是无返回值
*/
brandMapper.add(brand);
// 5、释放资源
sqlSession.close();
}
}
接口:
package com.itheima.pojo.mapper;
import com.itheima.pojo.Brand;
import java.util.List;
public interface BrandMapper {
/**
* 添加功能
* 结果返回void
*/
void add(Brand brand);
}
sql映射文件:
细节:这里的SQL语句是插入 不是查询所以查询的结果数据不用封装到对象的属性当中,因此也用不到ResultMap方法, 但是SQL语句当中的占位符一定要和传过来的对象属性名一样,因为传过来的对象属性名当中是在测试程序那里封装好的用户想要插入到数据库当中的数据
<?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:名称空间
id="" 引号里面是唯一的 用过之后就要用其他的了 所以需要用到Mapper代理开发
-->
<mapper namespace="com.itheima.pojo.mapper.BrandMapper">
<!-- resultMap 方法:
1、定义<resultMap> 标签 (其中 id 值 随便写、 type 变成了SQL语句返回类型Brand对象)
2、使用resultMap属性 替换了 resultType属性
-->
<resultMap id="brandResultMap" type="com.itheima.pojo.Brand">
<!--
id: 完成主键的映射(就是数据库id字段和实体类Brand的属性名不同 然后通过column和property分别表示出来即可得到结果)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
result: 完成一般字段的映射(就是除了id其他的字段)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
在此项目中 是数据库中字段 brand_name 和 company_name 和实体类属性名不同 不包括id字段
所以下列的操作是对一般字段的映射
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyNam" />
</resultMap>
<!-- 插入数据 -->
<insert id="add">
insert into tb_brand(brand_name, company_name, ordered, description, status) values
(#{brandName},#{companyNam},#{ordered},#{description},#{status});
</insert>
</mapper>
测试结果 (有个小细节):
因此需要我们手动提交事务:
如果我们不想每次都写手动提交事务的话、还可以通过传参true/false 默认帮我们提交事务:
package com.itheima.test;
import com.itheima.pojo.Brand;
import com.itheima.pojo.mapper.BrandMapper;
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.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 测试代码的程序
*/
public class MyBatisTest {
@Test
/**
* 测试方法
* 模拟用户添加操作
* 封装成对象的形式
*/
public void testAdd() throws IOException {
// 接收参数
int status =1;
String companyNam ="波导手机";
String brandName ="波导";
String description ="手机中的战斗机";
int ordered =100;
// 封装对象
Brand brand =new Brand();
brand.setStatus(status);
brand.setBrandName(brandName);
brand.setCompanyNam(companyNam);
brand.setDescription(description);
brand.setOrdered(ordered);
// 1、 加载核心配置文件,获取SqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2、获取SqlSession对象, 用它来执行sql
/**
* 这里通过传参 true/false 可以默认帮我们提交事务
* true : 默认提交事务
* false:不提交事务
*/
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 3、获取Mapper接口的代理对象 (解决硬编码问题)
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
// 4、执行方法
/**
* 注意: add方法 的返回类型为void 也就是无返回值
*/
brandMapper.add(brand);
/**
* 因为会默认把我们事务改为手动、并且回滚事务,所以我们表格会未插入成功,因此我们需要手动提交事务
*/
// sqlSession.commit();
// 5、释放资源
sqlSession.close();
}
}
第二种添加方式:
细节: 注意这里的主键id 最终通过对象getId拿即可~
sql映射文件:
<?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:名称空间
id="" 引号里面是唯一的 用过之后就要用其他的了 所以需要用到Mapper代理开发
-->
<mapper namespace="com.itheima.pojo.mapper.BrandMapper">
<!-- resultMap 方法:
1、定义<resultMap> 标签 (其中 id 值 随便写、 type 变成了SQL语句返回类型Brand对象)
2、使用resultMap属性 替换了 resultType属性
-->
<resultMap id="brandResultMap" type="com.itheima.pojo.Brand">
<!--
id: 完成主键的映射(就是数据库id字段和实体类Brand的属性名不同 然后通过column和property分别表示出来即可得到结果)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
result: 完成一般字段的映射(就是除了id其他的字段)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
在此项目中 是数据库中字段 brand_name 和 company_name 和实体类属性名不同 不包括id字段
所以下列的操作是对一般字段的映射
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyNam" />
</resultMap>
<!-- 插入数据 -->
<!-- 我们可以在这里给每个id属性 赋上true 从此我们可以以后添加完之后把主键返回 -->
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert into tb_brand(brand_name, company_name, ordered, description, status) values
(#{brandName},#{companyNam},#{ordered},#{description},#{status});
</insert>
</mapper>
程序测试:
package com.itheima.test;
import com.itheima.pojo.Brand;
import com.itheima.pojo.mapper.BrandMapper;
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.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 测试代码的程序
*/
public class MyBatisTest {
@Test
/**
* 测试方法
* 模拟用户添加操作
* 封装成对象的形式
*/
public void testAdd() throws IOException {
// 接收参数
int status =1;
String companyNam ="波导手机";
String brandName ="波导";
String description ="手机中的战斗机";
int ordered =100;
// 封装对象
Brand brand =new Brand();
brand.setStatus(status);
brand.setBrandName(brandName);
brand.setCompanyNam(companyNam);
brand.setDescription(description);
brand.setOrdered(ordered);
// 1、 加载核心配置文件,获取SqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2、获取SqlSession对象, 用它来执行sql
/**
* 这里通过传参 true/false 可以默认帮我们提交事务
* true : 默认提交事务
* false:不提交事务
*/
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 3、获取Mapper接口的代理对象 (解决硬编码问题)
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
// 4、执行方法
/**
* 注意: add方法 的返回类型为void 也就是无返回值
*/
brandMapper.add(brand);
/**
* 拿到插入该条数据的主键id、 通过对象拿即可 但是要在sql映射文件当中设置id为true
* 要不然拿到为null, 因为Brand对象当中本来就没有为id属性赋值
*/
System.out.println(brand.getId());
// 5、释放资源
sqlSession.close();
}
}
数据结果:
三、修改操作
第一种修改方式 全部字段修改:
测试程序:
package com.itheima.test;
import com.itheima.pojo.Brand;
import com.itheima.pojo.mapper.BrandMapper;
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.IOException;
import java.io.InputStream;
/**
* 测试代码的程序
*/
public class MyBatisTest {
@Test
/**
* 模拟用户想修改 id字段为6的全部字段信息
*/
public void testAdd() throws IOException {
// 接收参数
int status =1;
String companyNam ="菠萝手机";
String brandName ="菠萝";
String description ="手机中的战斗机";
int ordered =500;
int id =6;
// 封装对象
Brand brand =new Brand();
brand.setStatus(status);
brand.setBrandName(brandName);
brand.setCompanyNam(companyNam);
brand.setDescription(description);
brand.setOrdered(ordered);
brand.setId(id);
// 1、 加载核心配置文件,获取SqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
/**
* 注意要设置为true : 自动提交事务
*/
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 3、获取Mapper接口的代理对象 (解决硬编码问题)
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
// 4、执行方法
int count =brandMapper.update(brand);
System.out.println(count);
// 5、释放资源
sqlSession.close();
}
}
接口:
package com.itheima.pojo.mapper;
import com.itheima.pojo.Brand;
public interface BrandMapper {
/**
* 修改操作 修改全部字段
* 修改操作当中:
* 返回类型为int: 返回的是受影响的行数
* 返回类型为void:没有返回值
*/
int update(Brand brand);
}
sql映射文件:
<?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:名称空间
id="" 引号里面是唯一的 用过之后就要用其他的了 所以需要用到Mapper代理开发
-->
<mapper namespace="com.itheima.pojo.mapper.BrandMapper">
<!-- resultMap 方法:
1、定义<resultMap> 标签 (其中 id 值 随便写、 type 变成了SQL语句返回类型Brand对象)
2、使用resultMap属性 替换了 resultType属性
-->
<resultMap id="brandResultMap" type="com.itheima.pojo.Brand">
<!--
id: 完成主键的映射(就是数据库id字段和实体类Brand的属性名不同 然后通过column和property分别表示出来即可得到结果)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
result: 完成一般字段的映射(就是除了id其他的字段)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
在此项目中 是数据库中字段 brand_name 和 company_name 和实体类属性名不同 不包括id字段
所以下列的操作是对一般字段的映射
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyNam" />
</resultMap>
<!-- 修改操作 -->
<update id="update">
update tb_brand
set brand_name = #{brandName},
company_name =#{companyNam},
ordered =#{ordered},
description =#{description},
status =#{status}
where id = #{id};
</update>
</mapper>
测试结果:
修改前的数据库信息:
修改后的数据库信息:
第二种修改方式: 动态修改
细节: 动态修改:就把数据库当中的所有字段都在sql映射文件当中先<if>写出来再说
也就是说有的业务当中:不需要用户把数据库中的整行数据给修改了,修改某个字段数据即可修改成功即可
测试程序:
package com.itheima.test;
import com.itheima.pojo.Brand;
import com.itheima.pojo.mapper.BrandMapper;
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.IOException;
import java.io.InputStream;
/**
* 测试代码的程序
*/
public class MyBatisTest {
@Test
/**
* 假设这里我们动态修改数据库信息
* 只接收用户的几个数据而已 不是全部字段数据信息
* 假设这里用户只想修改id为6 的brandName字段
*/
public void testAdd() throws IOException {
// 接收参数
String brandName ="我的名字叫桃子";
int id =6;
// 封装对象
Brand brand =new Brand();
brand.setBrandName(brandName);
brand.setId(id);
// 1、 加载核心配置文件,获取SqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
/**
* 注意要设置为true : 自动提交事务
*/
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 3、获取Mapper接口的代理对象 (解决硬编码问题)
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
// 4、执行方法
int count =brandMapper.update(brand);
System.out.println(count);
// 5、释放资源
sqlSession.close();
}
}
接口:
package com.itheima.pojo.mapper;
import com.itheima.pojo.Brand;
public interface BrandMapper {
/**
* 修改操作 修改全部字段
* 修改操作当中:
* 返回类型为int: 返回的是受影响的行数
* 返回类型为void:没有返回值
*/
int update(Brand brand);
}
sql映射文件:
<?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:名称空间
id="" 引号里面是唯一的 用过之后就要用其他的了 所以需要用到Mapper代理开发
-->
<mapper namespace="com.itheima.pojo.mapper.BrandMapper">
<!-- resultMap 方法:
1、定义<resultMap> 标签 (其中 id 值 随便写、 type 变成了SQL语句返回类型Brand对象)
2、使用resultMap属性 替换了 resultType属性
-->
<resultMap id="brandResultMap" type="com.itheima.pojo.Brand">
<!--
id: 完成主键的映射(就是数据库id字段和实体类Brand的属性名不同 然后通过column和property分别表示出来即可得到结果)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
result: 完成一般字段的映射(就是除了id其他的字段)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
在此项目中 是数据库中字段 brand_name 和 company_name 和实体类属性名不同 不包括id字段
所以下列的操作是对一般字段的映射
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyNam" />
</resultMap>
<!-- 修改操作 -->
<update id="update">
update tb_brand
<set>
<if test="brandName !=null and brandName !='' ">
brand_name = #{brandName},
</if>
<if test="companyNam !=null and brandName !='' ">
company_name =#{companyNam},
</if>
<if test="ordered !=null">
ordered =#{ordered},
</if>
<if test="description !=null and brandName !='' ">
description =#{description},
</if>
<if test="status !=null ">
status =#{status}
</if>
</set>
where id = #{id};
</update>
</mapper>
改正:!="" 上面写错了.
结果:
修改前的数据库信息:
修改后的数据库信息:
四、删除操作
第一种 删除一个:
测试程序:
package com.itheima.test;
import com.itheima.pojo.Brand;
import com.itheima.pojo.mapper.BrandMapper;
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.IOException;
import java.io.InputStream;
/**
* 测试代码的程序
*/
public class MyBatisTest {
@Test
/**
* 删除操作 通过id删除
* 假设模拟接收用户输入的删除id为 6
*/
public void testAdd() throws IOException {
// 接受用户参数
int id =6;
// 封装到Brand对象
Brand brand =new Brand();
brand.setId(id);
// 1、 加载核心配置文件,获取SqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
/**
* 注意要设置为true : 自动提交事务
*/
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 3、获取Mapper接口的代理对象 (解决硬编码问题)
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
// 4、执行方法
int count =brandMapper.delectById(brand);
System.out.println(count);
// 5、释放资源
sqlSession.close();
}
}
接口:
package com.itheima.pojo.mapper;
import com.itheima.pojo.Brand;
public interface BrandMapper {
/**
* 删除功能
* 通过 id 删除一个
*/
int delectById(Brand brand);
}
sql映射文件:
<?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:名称空间
id="" 引号里面是唯一的 用过之后就要用其他的了 所以需要用到Mapper代理开发
-->
<mapper namespace="com.itheima.pojo.mapper.BrandMapper">
<!-- resultMap 方法:
1、定义<resultMap> 标签 (其中 id 值 随便写、 type 变成了SQL语句返回类型Brand对象)
2、使用resultMap属性 替换了 resultType属性
-->
<resultMap id="brandResultMap" type="com.itheima.pojo.Brand">
<!--
id: 完成主键的映射(就是数据库id字段和实体类Brand的属性名不同 然后通过column和property分别表示出来即可得到结果)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
result: 完成一般字段的映射(就是除了id其他的字段)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
在此项目中 是数据库中字段 brand_name 和 company_name 和实体类属性名不同 不包括id字段
所以下列的操作是对一般字段的映射
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyNam" />
</resultMap>
<!-- 删除操作 -->
<delete id="delectById">
delete from tb_brand where id =#{id};
</delete>
</mapper>
测试结果:
未删除前的数据库信息:
删除后的数据库信息:
第二种方式:批量删除
程序测试:
package com.itheima.test;
import com.itheima.pojo.mapper.BrandMapper;
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.IOException;
import java.io.InputStream;
/**
* 测试代码的程序
*/
public class MyBatisTest {
@Test
/**
* 删除操作: 批量删除 通过多个id同时进行删除操作
*/
public void testAdd() throws IOException {
// 接受用户参数
int[] ids ={2,3};
// 1、 加载核心配置文件,获取SqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
/**
* 注意要设置为true : 自动提交事务
*/
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 3、获取Mapper接口的代理对象 (解决硬编码问题)
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
// 4、执行方法
brandMapper.delectByIds(ids);
// 5、释放资源
sqlSession.close();
}
}
接口:
package com.itheima.pojo.mapper;
public interface BrandMapper {
/**
* 批量删除 因为会同时批量删除多个id字段的数据 因此参数用数组
*/
void delectByIds(int[] ids);
}
sql映射文件:
细节1:因为在接口当中mybatis会把数组转换成Map集合, (array=数组)的形式 ,所以我们在sql映射文件当中<foreach>增强for遍历标签当中 collection="array" 就相当于遍历array,又因为array=数组, 所以就相当于遍历数组(遍历id) 要记得再加上一个item ="id"属性
细节2: 一定要用 separator="," 逗号符隔开, 因为in(id,id,id)需要用到逗号
再解释理解一波:(记得要再加上一个item ="id"的属性)
<?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:名称空间
id="" 引号里面是唯一的 用过之后就要用其他的了 所以需要用到Mapper代理开发
-->
<mapper namespace="com.itheima.pojo.mapper.BrandMapper">
<!-- resultMap 方法:
1、定义<resultMap> 标签 (其中 id 值 随便写、 type 变成了SQL语句返回类型Brand对象)
2、使用resultMap属性 替换了 resultType属性
-->
<resultMap id="brandResultMap" type="com.itheima.pojo.Brand">
<!--
id: 完成主键的映射(就是数据库id字段和实体类Brand的属性名不同 然后通过column和property分别表示出来即可得到结果)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
result: 完成一般字段的映射(就是除了id其他的字段)
column:表的列名(数据库的字段名)
property:实体类(Brand类)的属性名
在此项目中 是数据库中字段 brand_name 和 company_name 和实体类属性名不同 不包括id字段
所以下列的操作是对一般字段的映射
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyNam" />
</resultMap>
<!-- 批量删除操作 -->
<!--
小细节:mybatis会将接口当中的数组参数,封装为一个Map集合
* 默认:array = 数组
因此 collection属性当中 我们需要写array 而不能写接口当中数组的名字ids
如果真的想在collection属性当中添加接口的数组名 那么就需要在接口参数那里添加上注解
-->
<delete id="delectByIds">
delete from tb_brand where id
in (
<foreach collection="array" item="id" separator=",">
#{id}
</foreach>
)
</delete>
<!--
这里的foreach标签相当于增强for遍历delectByIds接口当中的数组参数
因此 我们需要用到separator属性 把遍历出来的 全部#{id} 用,隔开 要不然sql语句会是错误的
把数组里面传递过来的 id 参数 依次遍历出来 当有多个id的时候这里会遍历成:#{id},#{id},#{id}
-->
</mapper>
非想用接口当中的参数名的话:需要在接口参数那里加上注解 (
@Param("")括号里面的名字要和传递过来的id数组名字一样,并且collection也要等于该名字,collection中等于该数组名字表示遍历该数组【因为该数组是客户端请求过来的批量删除id数据】)
测试结果:
未删除前的数据库信息:
删除后的数据库信息:
五、注解完成增删改查
(效率比mybatis更快 不用再去xml SQL映射文件当中添加增删改查的sql语句了 直接通过注解就能完成增删改查、 但是只针对简单的SQL语句)