Mybatis的学习笔记(IDEA快捷键,参数占位符,转义符)

一、Mybatis的使用:

Mybatis是一款优秀的持久层(负责将数据保存到数据库额那一层)框架,用于简化JDBC的开发。

框架的概念是:框架是一个半成品的软件,是一套可重用的、通用的、软件基础代码模型。

第1步:环境准备

1. 创建表,导数据:

复制下面代码到Navicat,创建数据库mybatis,新建表tb_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','男','西安');

在Navicat中点击 查询-新建查询-粘贴代码-运行:

刷新一下就将表插入成功,数据成功显示: 

2. 创建模块,导入坐标

Project Structure - Modules - New Module,新建项目:

 

创建名为mybatis-demo的子文件夹:

在pom.xml文件里,导入mybatis、mysql、junit单元测试、slf4j日志的依赖和驱动模块,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>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--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>

    </dependencies>


</project>

第2步:编写MyBatis核心配置文件

指定数据库的连接信息,避免硬编码(将连接信息直接写死在代码或配置文件中)问题。

在resources下创建mybatis-config.xml配置文件,粘贴如下内容:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://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://localhost:3306/mybatis?useSSL=false&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="111111"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="UserMapper.xml"/>
    </mappers>
</configuration>

通过配置<mappers>元素,我们可以将Mapper接口与对应的映射文件关联起来,使MyBatis自动解析和执行Mapper接口中定义的SQL语句。

<package>元素指定SQL映射文件UserMapper.xml),MyBatis会自动扫描该配置文件,注册到MyBatis的配置中。

当MyBatis解析到Mapper接口时,会根据接口的名称和映射文件的规则,自动查找对应的映射文件并加载其中的SQL语句。这样,我们可以通过调用Mapper接口的方法来执行对应的SQL语句,而无需编写繁琐的SQL语句和映射配置。

第3步:编写SQL映射文件

书写sql语句,统一进行管理,避免硬编码问题。

 在resources下创建UserMapper.xml,粘贴如下代码:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="test">
    <select id="selectAll" resultType="com.itheima.pojo.User">
        select * from tb_user;
    </select>
</mapper>

id属性指定了SQL操作的唯一标识符,resultType指定了查询结果的类型,<select>标签内使具体的SQL查询语句。

第4步:启动

1. 创建pojo实体类

在java下创建com.itheima.pojo.User类。按住Alt+insert——可以设置Set方法和toString方法:

 

2. 创建启动类

在java下创建com.itheima.MybatisDemo,在其中写入如下代码:

//1. 加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "mybatis-config.xml"; //mybatis-config.xml是核心配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.获取sqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
//3.执行SQL语句
        List<User> users = sqlSession.selectList("test.selectAll");
        System.out.println(users);
//4.释放资源
        sqlSession.close();

第1、2步实现与数据库的连接,第3步创建接口,第4步创建对象,第5步调用SQL语句查询返回结果。

1. String resource = "mybatis-config.xml" :定义了一个字符串变量resource,用于存储MyBatis的核心配置文件路径

2. InputStream inputStream = Resources.getResourceAsStream(resource) :通过Resources.getResourceAsStream()方法加载核心配置文件并返回一个InputStream对象。

3. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream) :使用SqlSessionFactoryBuilder类的build()方法创建SqlSessionFactory对象。SqlSessionFactory是MyBatis的核心接口,用于创建SqlSession对象,从而执行数据库操作。

4. SqlSession sqlSession = sqlSessionFactory.openSession()通过SqlSessionFactory的openSession()方法创建一个SqlSession对象。SqlSession是MyBatis的会话对象,可以用来执行SQL语句和管理事务。

5. List<User> users = sqlSession.selectList("test.selectAll") :调用SqlSession对象的selectList()方法执行SQL查询操作,将结果封装为一个List<User>类型的对象。其中test.selectAll是映射文件中查询语句的唯一标识符

可以正常输出数据库内容:

二、Mapper代理开发

在前面代码的基础上进行增添和修改。

第1步:添加接口

1. 定义与SQL映射文件同名的Mapper接口——在java-com-itheima下创建mapper包,定义UserMapper接口:

在接口中写入返回类型和SQL语句的唯一标识(SQL映射文件中对应SQL语句的id)同名的方法:

List<User> selectAll();

第2步:统一目录

2. 将Mapper接口和SQL映射文件放置在同一目录下——把UserMapper接口和配置文件放在同一层目录下

在resources下创建com-itheima-mapper包,将UserMapper.xml放在mapper包下:

第3步:修改SQL映射文件

3. 设置SQL映射文件的namespace属性为Mapper接口全限定名(完整路径)

第4步:修改MyBatis核心配置文件

4. 修改MyBatis核心配置文件中SQL映射文件地址

UserMapper.xml的路径有所改动,右键 - Copy Path/Referenc - Path From Source Root 获取更新路径:

 

 <mappers>元素是MyBatis配置文件中的一个元素,用于指定Mapper接口的扫描配置。

<package>元素用于指定要扫描的Mapper接口所在的包名。

<mappers>
     <package name="com.itheima.mapper"/>
</mappers>

第5步:修改执行类

5. 在MyBatisDemo中修改执行SQL的部分,通过SqlSession的getMapper方法获取Mapper接口的代理对象:

UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);

6. 调用对应方法执行SQL:

List<User> users = userMapper.selectAll();
System.out.println(users);

UserMapper接口的定义可以将对数据库的操作与具体的实现(UserMapper.xml实现)分离开来,让开发人员能够更方便地理解和使用这些数据库操作。

SqlSessionFactory是MyBatis的核心类之一,用于创建和管理SqlSession对象。

SqlSession对象获取UserMapper接口时,是通过MyBatis的动态代理机制来生成UserMapper接口的代理对象。这个代理对象包含了具体的数据库操作逻辑,实现了接口中定义的方法。

然后,代理对象会根据接口的方法名和参数信息,【找到对应的Mapper XML文件中的SQL语句】,这是通过命名规则和Mapper XML文件的配置来实现的。最后,调用的方法会执行相应的SQL语句,并返回结果。

三、核心配置文件完成查询

 

environments:可以配置多个environment通过default属性切换不同的environment,配置数据库连接环境信息。

resulttype:类型别名

3.1 前期准备

新建数据库:

drop table if exists tb_brand;
create table tb_brand
(
	id int primary key auto_increment,
	brand_name varchar(20),
	company_name varchar(20),
	ordered int,
	description varchar(100),
	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实体类放在pojo目录下,在test目录下创建一个java包,新建MyBatisTest测试类:

 

3.2 查询所有数据

第1步:编写接口方法:

在mapper下创建BrandMapper接口,写入如下代码:

public interface BrandMapper {
    public List<Brand> selectAll();
}

第2步:编写SQL映射文件:

定义名称空间为BrandMapper全类名,id写接口中的方法,resjltType写Brand实体类,在<select>中写SQL语句:

<mapper namespace="com.itheima.mapper.BrandMapper">
    <select id="selectAll" resultType="com.itheima.pojo.Brand">
        select * from tb_brand;
    </select>
</mapper>

第3步:执行测试方法

在测试类中注意:1. 非静态方法(无static)2. 方法名无传入参数 3. 要加注解@Test才能编译运行

public class MyBatisTest {
    @Test
    public void testSelectAll() throws  IOException {
        //1.获取SqlSessionFactory
        String resource = "mybatis-config.xml"; //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();
    }
}

下面是结果:

之所以出现很多null是因为数据库采用下划线命名,实体类采用驼峰命名:

可以有如下解决方案:1.起别名;2.sql片段。见文章末尾。3.resultMap,在这里重点讲解:

1. 定义<resultMap>标签,id里填写唯一标识符,提供给resultMap引用,type指示返回的实体类全类名。

2. 在<resultMap>下定义<result>,column中写数据库中的字段,property中写实体类中的字段。

3.3 查询特定数据

1. 编写接口方法:

在BrandMapper接口中写入方法(返回Brand实体类,传入参数名ID):

public Brand selectSingle(int ID);

2. 编写SQL映射文件

注意:id = #{ID},等号左边的id是实体类中的变量名,等号右边的ID是接口方法中传入的参数。

<select id="selectSingle" resultMap="brandResultMap">
      select * from tb_brand where id=#{ID};
</select>

3. 执行方法,测试

@Test
    public void testSelectById() throws  IOException {
        //接收参数
        int id = 2;
        //1.获取SqlSessionFactory
        String resource = "mybatis-config.xml"; //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.selectSingle(id);
        System.out.println(brand);
        //5.释放资源
        sqlSession.close();
    }

实现逻辑:首先在Test里获取一个参数id,然后调用brandMapper中的selectById方法,传入的参数是ID,然后相当于是调用了映射文件中的sql语句,返回了符合结果的Brand对象给brand,然后输出这个brand结果。

 3.4 多条件查询

需求背景:输入多个查询参数进行模糊查询。

下面分3种传参方式(散装参数,对象参数,集合参数)分别进行说明:

3.4.1. 散装参数

1. 添加BrandMapper接口方法:

public List<Brand> selectByCondition(@Param("STATUS") int status, @Param("BRANDNAME") String brandName, @Param("COMPANYNAME") String companyName);

— — — — — — — —知识加油站 — — — — — — — — —

1. @Param注解是MyBatis框架中的一个注解,用于指定方法参数在SQL语句中的命名参数,它的作用是为了在SQL语句中引用方法参数时,提供一个具有可读性的名称。

User getUserByIdAndUsername(@Param("userId") int id, @Param("username") String name);

在上面的示例中@Param注解分别给id和name参数指定了名称,然后在SQL语句中使用#{userId}和#{username}来引用这两个参数。

2. %是一个通配符,用于模糊匹配字符串。它可以匹配任意数量的字符(包括零个字符)。

3. LIKE是一个用于模糊匹配的操作符。用于在文本字段中进行模糊匹配。

— — — — — — — — — — — — — — — — — —— — — — 

2. 编写SQL映射文件:

#花括号里的内容是接口方法中@Param注解里定义的名称,等号左边是数据库中的字段。

注意:brand_name和company_name要进行模糊匹配

<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语句部分。

@Test
public void testSelectAll() throws IOException {
//— — — — — — — —修改1:接收参数— — — — — — — —
    int status = 1;
    String companyName = "华为";
    String brandName = "华为";
    companyName = "%" + companyName + "%";
    brandName = "%" + brandName + "%";
//— — — — — — — — — — — — — — — — — — —
//1. 加载mybatis的核心配置文件,获取SqlSessionFactory
    String resource = "mybatis-config.xml"; //mybatis-config.xml是核心配置文件
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.获取sqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
//— — — — — — — —修改2:执行SQL语句— — — — — — — —
    BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    List<Brand> res= brandMapper.selectByCondition(status,brandName,companyName);
    System.out.println(res);
//— — — — — — — — — — — — — — — — — — — — — — —
//4.释放资源
    sqlSession.close();
}
3.4.2. 对象参数

1. 添加BrandMapper接口方法:

public List<Brand> selectByCondition(Brand brand);

2. 编写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. 执行测试方法:

    int status = 1;
    String companyName = "华为";
    String brandName = "华为";
    companyName = "%" + companyName + "%";
    brandName = "%" + brandName + "%";
//— — — — — — — —修改1:封装参数— — — — —
    Brand brand = new Brand();
    brand.setBrandName(brandName);
    brand.setCompanyName(companyName);
    brand.setStatus(status);
//— — — — — — — — — — — — — — — — — — —
//— — — — — — — —修改2:传入对象参数— — — — — — — —
    List<Brand> res= brandMapper.selectByCondition(brand);
    System.out.println(res);
//— — — — — — — — — — — — — — — — — — — — — — —
3.4.3. 集合参数

1. 添加BrandMapper接口方法:

public List<Brand> selectByCondition(Map map);

2. 编写SQL映射文件:同上

3. 执行测试方法:

    int status = 1;
    String companyName = "华为";
    String brandName = "华为";
    companyName = "%" + companyName + "%";
    brandName = "%" + brandName + "%";
//— — — — — — — —修改1:封装集合— — — — — — — —
    Map map = new HashMap(); //注意new的是HashMap()
    map.put("status",status);
    map.put("companyName",companyName);
    map.put("brandName",brandName);
//— — — — — — — — — — — — — — — — — — —
//— — — — — — — —修改2:传入对象参数— — — — — — — —
    List<Brand> res= brandMapper.selectByCondition(map);
    System.out.println(res);
//— — — — — — — — — — — — — — — — — — — — — — —

3.5 添加操作

1. 添加BrandMapper接口方法:

public void ADD(Brand brand);

2. 编写SQL映射文件:

<insert id="ADD">
        insert into tb_brand(brand_name,company_name,ordered,description,status)
        values(#{brandName},#{companyName},#{ordered},#{description},#{status});
</insert>

3. 执行测试方法:

//— — — — — — — —修改1:接收参数— — — — — — — —
    String companyName = "波导手机";
    String brandName = "波导";
    String description="手机中的战斗机";
    int ordered=100;
    int status = 1;
//— — — — — — — — — — — — — — — — — — — — — —
//— — — — — — — —修改2:封装对象— — — — — — — —
    Brand brand = new Brand();
    brand.setBrandName(brandName);
    brand.setStatus(status);
    brand.setDescription(description);
    brand.setCompanyName(companyName);
    brand.setOrdered(ordered);
//— — — — — — — — — — — — — — — — — — — — —
//— — — — — — — —修改3:执行方法提交— — — — — — — —
    brandMapper.ADD(brand);
    sqlSession.commit();
//— — — — — — — — — — — — — — — — — — — — — — —

设置下面参数可以自动提交: 

主键返回

useGeneratedKeys属性是一个布尔值,用于指定是否使用数据库自动生成的键。如果设置为true,MyBatis会将自动生成的键返回给Java对象。

keyProperty属性是一个字符串,用于指定返回的自动生成的键要映射到Java对象的哪个属性上。这个属性应该与Java对象的属性名相匹配(换言之对应的名要与Brand实体类中的变量对应)。

//— — — — — — — —打印Id值— — — — — — — —
    sqlSession.commit();
    System.out.println(brand.getId());
//— — — — — — — — — — — — — — — — — — —

3.6 修改操作

1. 修改全部字段

1. 添加BrandMapper接口方法:

public void update(Brand brand);

2. 编写SQL映射文件:

等号左边是数据库字段名,等号右边是Java对象的字段名(也就是实体类的字段名)。

<update id="update">
    update tb_brand
    set
        brand_name=#{brandName},
        company_name=#{companyName},
        ordered=#{ordered},
        description=#{description},
        status=#{status}
    where id=#{id};
</update>

3. 执行测试方法:

//— — — — — — 修改1:接收修改参数— — — — — —
    String companyName = "66手机";
    String brandName = "波导";
    String description="手机中的7788";
    int ordered=100;
    int status = 1;
    int id=4;
//— — — — — — — — — — — — — — — — — — — —
//— — — — — — — —修改2:封装对象— — — — — — — —
    Brand brand = new Brand();
    brand.setBrandName(brandName);
    brand.setStatus(status);
    brand.setDescription(description);
    brand.setCompanyName(companyName);
    brand.setOrdered(ordered);
    brand.setId(id);
//— — — — — — — — — — — — — — — — — — — — —
//— — — — — — — —执行方法添加— — — — — — —
    brandMapper.update(brand);
    sqlSession.commit();
//— — — — — — — — — — — — — — — — — — —

2. 修改动态字段

1. 添加BrandMapper接口方法:

public void update(Brand brand);

2. 编写SQL映射文件:

 通过使用<set>标签,可以在更新操作中根据条件动态地生成SET子句,只包含满足条件的列和对应的值。可以避免在生成的SQL语句中出现不必要的逗号或不完整的SET子句。

<update id="update">
    update tb_brand
    <set>
        <if test="brandName != null and brandName != ''">
            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>

3. 执行测试方法:

//— — — — — — 修改1:接收修改参数— — — — — —
    String companyName = "Space-X!!";
    int id=6;
//— — — — — — 修改2:封装对象— — — — — — — —
    Brand brand = new Brand();
    brand.setCompanyName(companyName);
    brand.setId(id);
//— — — — — — — — — — — — — — — — — — — — —
//— — — — — — — —执行方法添加— — — — — — —
    brandMapper.update(brand);
    sqlSession.commit();

3.7 删除操作

1. 删除单个

1. 添加BrandMapper接口方法:

public void delete(int id);

2. 编写SQL映射文件:

<delete id="deleteById">
    delete from tb_brand where id = #{id};
</delete>

3. 执行测试方法:

//— — — — — — — —执行删除方法— — — — — — —
    int num=8;
    brandMapper.deleteById(num);
    sqlSession.commit();
//— — — — — — — — — — — — — — — — — — —

2. 删除多个

1. 添加BrandMapper接口方法:

要添加@Param注解,因为是多个元素。

ids:。

public void deleteById(@Param("ids") int[] ids);

2. 编写SQL映射文件:

collection:。item:。sepatator:。

<delete id="deleteById">
    delete from tb_brand where id
    in(
        <foreach collection="ids" item="id" separator=",">
            #{id}
        </foreach>
    );
</delete>

3. 执行测试方法:

//— — — — — — — —执行删除方法— — — — — — —
    int [] ids={5,6,7};
    brandMapper.deleteById(ids);
    sqlSession.commit();
//— — — — — — — — — — — — — — — — — — —

四、注解完成增删改查

注解用来完成简单功能(不适合动态SQL要if和foreach这些),配置文件完成复杂功能

5.1 查询@Select

1. 查询所有:

更改:编写SQL映射文件 -> 编写注解

@Select("select * from tb_brand")
@Result(column = "brand_name", property = "brandName")
@Result(column = "company_name", property = "companyName")
public List<Brand> selectAll();

2. 查询单个:

更改:编写SQL映射文件 -> 编写注解

@Select("select * from tb_brand where id=#{ID}")
@Result(column = "brand_name", property = "brandName")
@Result(column = "company_name", property = "companyName")
public Brand selectSingle(int ID);

5.2 添加@Insert

更改:编写SQL映射文件 -> 编写注解

@Insert("insert into tb_brand(brand_name,company_name,ordered,description,status)" +
  "values(#{brandName},#{companyName},#{ordered},#{description},#{status})")
public void ADD(Brand brand);

5.3 修改@Update

注解只适合修改某条数据的全部字段,否则会出现为null的情况:

@Update("update tb_brand set brand_name=#{brandName},company_name=#{companyName},ordered=#{ordered},description=#{description},status=#{status} where id =#{id}")
    public void update(Brand brand);

5.4 删除@Delete

注解只适合删除传入单个id的,多id的使用配置文件:

@Delete("delete from tb_brand where id=#{id}")
public void deleteById(int id);

五、动态条件查询

 应用场景:用户不一定填写完所有的查找条件,程序根据部分给定的查找条件完成查找。写在Mapper.xml配置文件里。

1. if 语法如下:

<if test="条件">
    判断
</if>

如果没有输入条件,应该输出所有,但下例会没有输出,不符合要求,因此可以加入一个恒等式:

 第2种方法可以用<where>标签替换where,这也是以后的默认做法:

2.choose 语法如下:

<choose>
     <when test="条件">
          判断
     </when>
     <otherwise>
          判断
     <otherwise>
</choose>

choose相当于是switch,when相当于是case,otherwise相当于是default。 

下面的写法在末尾加上otherwise,可以满足无输入的情况:

用<where>标签包裹是更好的方法,可以不写otherwise:

六、心得总结

6.1 学习复盘

1. 按住Alt+鼠标左键——可以对多行同时进行编辑。

6.2 面试真题

1、mybatis 中 #{}和 ${}的区别是什么?

  1. #{}带引号,${}不带引号;
  2. #{}可以防止SQL注入;
  3. ${}常用于数据库表名、order by子句;
  4. 一般能用#{}就不要使用${};

2、mybatis 是否支持延迟加载?延迟加载的原理是什么?

延迟加载其实就是讲数据加载时机推迟,比如推迟嵌套查询的时机。

延迟加载可以实现先查询主表,按需实时做关联查询,返回关联表结果集,一定程度上提高了效率。

mybatis仅支持关联对象association和关联集合对象collection的延迟加载,association是一对一,collection是一对多查询,在mybatis配置文件中可以配置lazyloadingEnable=true/false。

3、延迟加载的原理是什么?

使用CGLIB为目标对象建立代理对象,当调用目标对象的方法时进入拦截器方法。

比如调用a.getB().getName(),拦截器方法invoke()发现a.getB()为null,会单独发送事先准备好的查询关联B对象的sql语句,把B查询出来然后调用a.setB(b),也是a的对象的属性b就有值了,然后调用getName(),这就是延迟加载的原理。

4、mybatis一级缓存、二级缓存

1、一级缓存:指的是mybatis中sqlSession对象的缓存,当我们执行查询以后,查询的结果会同时存入sqlSession中,再次查询的时候,先去sqlSession中查询,有的话直接拿出,当sqlSession消失时,mybatis的一级缓存也就消失了,当调用sqlSession的修改、添加、删除、commit()、close()等方法时,会清空一级缓存。

2、二级缓存:指的是mybatis中的sqlSessionFactory对象的缓存,由同一个sqlSessionFactory对象创建的sqlSession共享其缓存,但是其中缓存的是数据而不是对象。当命中二级缓存时,通过存储的数据构造成对象返回。查询数据的时候,查询的流程是二级缓存 > 一级缓存 > 数据库。

3、如果开启了二级缓存,sqlSession进行close()后,才会把sqlSession一级缓存中的数据添加到二级缓存中,为了将缓存数据取出执行反序列化,还需要将要缓存的pojo实现Serializable接口,因为二级缓存数据存储介质多种多样,不一定只存在内存中,也可能存在硬盘中。

4、mybatis框架主要是围绕sqlSessionFactory进行的,具体的步骤:

定义一个configuration对象,其中包含数据源、事务、mapper文件资源以及影响数据库行为属性设置settings。
通过配置对象,则可以创建一个sqlSessionFactoryBuilder对象。
通过sqlSessionFactoryBuilder获得sqlSessionFactory实例。
通过sqlSessionFactory实例创建qlSession实例,通过sqlSession对数据库进行操作。
5、代码实例

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>   
    <!-- 加载类路径下的属性文件 -->  
    <properties resource="db.properties"/>  
 
    <!-- 设置类型别名 -->  
    <typeAliases>  
        <typeAlias type="cn.itcast.javaee.mybatis.app04.Student" alias="student"/>  
    </typeAliases>  
 
    <!-- 设置一个默认的连接环境信息 -->  
    <environments default="mysql_developer">  
 
        <!-- 连接环境信息,取一个任意唯一的名字 -->  
        <environment id="mysql_developer">  
            <!-- mybatis使用jdbc事务管理方式 -->  
            <transactionManager type="jdbc"/>  
            <!-- mybatis使用连接池方式来获取连接 -->  
            <dataSource type="pooled">  
                <!-- 配置与数据库交互的4个必要属性 -->  
                <property name="driver" value="${mysql.driver}"/>  
                <property name="url" value="${mysql.url}"/>  
                <property name="username" value="${mysql.username}"/>  
                <property name="password" value="${mysql.password}"/>  
            </dataSource>  
        </environment>  
 
        <!-- 连接环境信息,取一个任意唯一的名字 -->  
        <environment id="oracle_developer">  
            <!-- mybatis使用jdbc事务管理方式 -->  
            <transactionManager type="jdbc"/>  
            <!-- mybatis使用连接池方式来获取连接 -->  
            <dataSource type="pooled">  
                <!-- 配置与数据库交互的4个必要属性 -->  
                <property name="driver" value="${oracle.driver}"/>  
                <property name="url" value="${oracle.url}"/>  
                <property name="username" value="${oracle.username}"/>  
                <property name="password" value="${oracle.password}"/>  
            </dataSource>  
        </environment>  
    </environments>  
 
    <!-- 加载映射文件-->  
    <mappers>  
        <mapper resource="cn/itcast/javaee/mybatis/app14/StudentMapper.xml"/>  
    </mappers>  
 
</configuration>  

public class MyBatisTest {
 
    public static void main(String[] args) {
        try {
            //读取mybatis-config.xml文件
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
            //初始化mybatis,创建SqlSessionFactory类的实例
            SqlSessionFactory sqlSessionFactory =  new SqlSessionFactoryBuilder().build(resourceAsStream);
            //创建session实例
            SqlSession session = sqlSessionFactory.openSession();
            /*
             * 接下来在这里做很多事情,到目前为止,目的已经达到得到了SqlSession对象.通过调用SqlSession里面的方法,
             * 可以测试MyBatis和Dao层接口方法之间的正确性,当然也可以做别的很多事情,在这里就不列举了
             */
            //插入数据
            User user = new User();
            user.setC_password("123");
            user.setC_username("123");
            user.setC_salt("123");
            //第一个参数为方法的完全限定名:位置信息+映射文件当中的id
            session.insert("com.cn.dao.UserMapping.insertUserInformation", user);
            //提交事务
            session.commit();
            //关闭session
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5、mybatis如何防止sql注入

注意:但凡是sql注入漏洞的程序,都是因为程序要接受来自客户端用户输入的变量或URL传递的参数,并且这个变量或参数是组成sql语句的一部分,对于用户输入的内容或传递的参数,我们应该要时刻保持警惕,这是安全领域里的【外部数据不可信任】的原则,纵观web安全领域的各种攻击方式,大多数都是因为开发者违反了这个原则而导致的,所以自然能想到,就是变量的检测、过滤、验证下手,确保变量是开发者所预想的。

1、检查变量数据类型和格式

数据类型检查,sql执行前,要进行数据类型检查,如果是邮箱,参数就必须是邮箱的格式,如果是日期,就必须是日期格式;

只要是有固定格式的变量,在SQL语句执行前,应该严格按照固定格式去检查,确保变量是我们预想的格式,这样很大程度上可以避免SQL注入攻击。

如果上述例子中id是int型的,效果会怎样呢?无法注入,因为输入注入参数会失败。比如上述中的name字段,我们应该在用户注册的时候,就确定一个用户名规则,比如5-20个字符,只能由大小写字母、数字以及汉字组成,不包含特殊字符。此时我们应该有一个函数来完成统一的用户名检查。不过,仍然有很多场景并不能用到这个方法,比如写博客,评论系统,弹幕系统,必须允许用户可以提交任意形式的字符才行,否则用户体验感太差了。

2、过滤特殊符号

3、绑定变量,使用预编译语句

6、MyBatis中 #{}和${}的区别是什么

#{}是预编译处理,${}是字符串替换;

Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;

Mybatis在处理${}时,就是把${}替换成变量的值;

使用#{}可以有效的防止SQL注入,提高系统安全性。

7、Mybatis 中一级缓存与二级缓存

MyBatis的缓存分为一级缓存和 二级缓存。
一级缓存是SqlSession级别的缓存,默认开启。

二级缓存是NameSpace级别(Mapper)的缓存,多个SqlSession可以共享,使用时需要进行配置开启。

缓存的查找顺序:二级缓存 => 一级缓存 => 数据库

8、MyBatis如何获取自动生成的(主)键值

在<insert>标签中使用 useGeneratedKeys和keyProperty 两个属性来获取自动生成的主键值。

示例:

<insert id=”insertname” usegeneratedkeys=”true” keyproperty=”id”>
    insert into names (name) values (#{name}) 
</insert>

Java

9、简述Mybatis的动态SQL,列出常用的6个标签及作用

动态SQL是MyBatis的强大特性之一 基于功能强大的OGNL表达式。

动态SQL主要是来解决查询条件不确定的情况,在程序运行期间,根据提交的条件动态的完成查询

常用的标签:

<if> : 进行条件的判断

<where>:在<if>判断后的SQL语句前面添加WHERE关键字,并处理SQL语句开始位置的AND 或者OR的问题

<trim>:可以在SQL语句前后进行添加指定字符 或者去掉指定字符.

<set>:  主要用于修改操作时出现的逗号问题

<choose> <when> <otherwise>:类似于java中的switch语句.在所有的条件中选择其一

<foreach>:迭代操作

10、Mybatis 如何完成MySQL的批量操作

MyBatis完成MySQL的批量操作主要是通过<foreach>标签来拼装相应的SQL语句

例如:

<insert** id="insertBatch" >
    insert into tbl_employee(last_name,email,gender,d_id) values 
   <foreach** collection="emps" item="curr_emp" separator=","**>
      (#{curr_emp.lastName},#{curr_emp.email},#{curr_emp.gender},#{curr_emp.dept.id}) 
   </foreach>
</insert>

6.3 常见问题

6.3.1 IDEA不识别数据库解决方案

在IDEA的Database中选择Data Source-MySQL:

填写用户名、密码和数据库名称:

如果目标数据库下没有tb_user表,就点击那个小扳手:

然后到Schemas下勾选需要显示表的数据库即可:

以后可以直接在这里写sql语句并执行:

6.3.2 resource文件缺失

点击File-Project Structure,选中要作为resources文件的目录,右键点击Resources

6.3.3 MybatisX插件下载

  下载一个MyBatisX插件:

6.3.4 数据库和实体类中的变量名不一致

 方法1:起别名(BrandMapper.xml中的sql语句,对不一样的列名起别名,让别名和实体类的属性名一样)

 方法2:sql片段

<mapper namespace="com.itheima.mapper.BrandMapper">
    <sql id="brand_column">
        id,brand_name as brandName,company_name as companyName,ordered,description,status
    </sql>
    <select id="selectAll" resultType="com.itheima.pojo.Brand">
        select
        <include refid="brand_column"></include>
        from tb_brand;
    </select>
</mapper>

方法3:resultMap

1. 定义<resultMap>标签,id里填写唯一标识符,提供给resultMap引用,type指示返回的实体类全类名。

2. 在<resultMap>下定义<result>,column中写数据库中的字段,property中写实体类中的字段。

七、Mybatis重要知识点:

1.1 参数占位符

一共分为2种:#{}和${}。

其中#{}会被替换为问号(?),可以防止sql注入。 ${}会变成具体值,会存在sql注入的问题。

使用时机:参数传递的情况用#{}。表名或者列名不固定的情况下,用${}。

2.2 特殊字符处理

转义字符:小于 &lt;

CDATA区:<![CDATA[ 在此填写内容 ]]>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值