mybatis

目录

入门

是什么?

使用Mybatis操作数据库

操作数据库的步骤

1. 准备工作

2. 引入Mybatis的相关依赖,配置Mybatis(数据库连接信息)

3. 编写SQL语句(注解/XML)

4 单元测试

解决SQL警告与提示

JDBC(了解)

数据库连接池

好处

怎么样实现数据库连接池

常见的数据库连接池

默认的数据库连接池切换为Druid数据库连接池

在pom.xml文件中引入依赖

在application.properties中引入数据库连接配置

方式1:

方式2:

lombok

注解

使用

第1步:在pom.xml文件中引入依赖

第2步:在实体类上添加注解

基础操作

预编译SQL

SQL注入

优势

1. 性能更高

2. 更安全(防止SQL注入)

参数占位符

#{...}

${...}

1. 查询

根据主键ID查询

数据封装

原因

解决方案

条件查询

方式一

方式二(解决SQL注入风险)

参数名说明

参数名在不同的SpringBoot版本中,处理方案还不同:

2. 新增

主键返回

3. 更新

4. 删除

日志输入

Mybatis的XML配置文件

Mybatis的开发有两种方式

1. 注解(代码简单时使用)

2. XML(复杂时使用)

XML配置文件规范 (写在资源文件(resources)中用'/'当做'.'建立多级包)

XML配置文件实现

创建XML映射文件

编写XML映射文件

两个文件

接口文件

xml文件

MybatisX插件的使用

动态SQL

动态SQL-if

动态SQL-foreach

动态SQL-sql&include


入门

是什么?

持久层框架,用于简化JDBC的开发。

持久层:就是数据访问层(dao),是用来操作数据库的。

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

使用Mybatis操作数据库

在Mybatis中编写SQL查询代码,发送给数据库执行,数据库执行后返回结果。

Mybatis会把数据库执行的查询结果,使用实体类封装起来(一行记录对应一个实体类对象)

操作数据库的步骤

1. 准备工作

创建springboot工程,并导入 mybatis的起步依赖、mysql的驱动包。

<dependencies>
        <!-- mybatis起步依赖 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.0</version>
        </dependency>

        <!-- mysql驱动包依赖 -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
</dependencies>

数据库表user

实体类User

2. 引入Mybatis的相关依赖,配置Mybatis(数据库连接信息)

1.连接数据库的四大参数:

MySQL驱动类 

登录名

密码

数据库连接字符串

2.在springboot项目中,可以编写application.properties文件,配置数据库连接信息。我们要连接数据库,就需要配置数据库连接的基本信息,包括:driver-class-name、url 、username,password。

application.properties:

#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234

3. 编写SQL语句(注解/XML)

在创建出来的springboot工程中,在引导(启动)类所在包下,在创建一个包 mapper。在mapper包下创建一个接口 UserMapper ,这是一个持久层接口(Mybatis的持久层接口规范一般都叫 XxxMapper)。

UserMapper:

@Mapper
public interface UserMapper {
    //查询所有用户数据
    @Select("select * from user")
    public List<User> list();
}

@Mapper注解:

表示是mybatis中的Mapper接口

程序运行时:框架会自动生成接口的实现类对象(动态代理对象),并给交Spring的IOC容器管理

@Select注解:

就是select查询,用于书写select查询语句

4 单元测试

@SpringBootTest
public class MybatisQuickstartApplicationTests {
    
    @Autowired
    private UserMapper userMapper;
    
    @Test
    public void testList(){
        List<User> userList = userMapper.list();
        for (User user : userList) {
            System.out.println(user);
        }
    }

}

解决SQL警告与提示

默认我们在UserMapper接口上的@Select注解中编写SQL语句是没有提示的。如果想让idea给出提示,可以做如下配置:

选中语句,右击show context Actions ->inject language or reference ->mysql

配置完成之后,发现SQL语句中的关键字有提示了,但还存在不识别表名(列名)的情况:

产生原因:Idea和数据库没有建立连接,不识别表信息

解决方案:在Idea中配置MySQL数据库连接

JDBC(了解)

sun公司定义的一套操作所有关系型数据库的规范,即api接口。

各个数据库厂商去实现这套接口,提供数据库驱动jar包。

真正执行的代码是驱动jar包中的实现类。

Mybatis框架,就是对原始的JDBC程序的封装。

数据库连接池

是个容器,负责分配、管理数据库连接(Connection),程序在启动时,数据库连接池中创建一定数量的Connection对象

允许应用程序重复使用一个现有的数据库连接,而不重新建立

释放空闲时间超时的连接,来避免因为没有释放连接而引起的数据库连接遗漏

好处

1. 资源重用
2. 提升系统响应速度
3. 避免数据库连接遗漏

怎么样实现数据库连接池

官方(sun)提供了数据库连接池标准(javax.sql.DataSource接口)

功能:获取连接    public Connection getConnection() throws SQLException;

第三方组织必须按照DataSource接口实现

常见的数据库连接池

C3P0

DBCP

Druid(德鲁伊)性能优越,阿里巴巴开源的数据库连接池项目 ,功能强大,性能优秀,是Java语言最好的数据库连接池之一
Hikari (springboot默认)(追光者)性能优越

默认的数据库连接池切换为Druid数据库连接池

参考官方地址:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter

在pom.xml文件中引入依赖

<dependency>
    <!-- Druid连接池依赖 -->
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.8</version>
</dependency>

在application.properties中引入数据库连接配置
方式1:

spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.url=jdbc:mysql://localhost:3306/mybatis
spring.datasource.druid.username=root
spring.datasource.druid.password=1234

方式2:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
spring.datasource.username=root
spring.datasource.password=1234

lombok

通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,并可以自动化生成日志变量,简化java开发、提高效率。

注解

@Getter/@Setter为所有的属性提供get/set方法
@ToString会给类自动生成易阅读的  toString 方法
@EqualsAndHashCode根据类所拥有的非静态字段自动重写 equals 方法和  hashCode 方法
@Data提供了更综合的生成代码功能(@Getter  + @Setter + @ToString + @EqualsAndHashCode)
@NoArgsConstructor为实体类生成无参的构造器方法
@AllArgsConstructor为实体类生成除了static修饰的字段之外带有各参数的构造器方法。

使用

第1步:在pom.xml文件中引入依赖

<!-- 在springboot的父工程中,已经集成了lombok并指定了版本号,故当前引入依赖时不需要指定version -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

第2步:在实体类上添加注解

在实体类上添加了@Data注解,那么这个类在编译时期,就会生成getter/setter、equals、hashcode、toString等方法。

说明:@Data注解中不包含全参构造方法,通常在实体类上,还会添加上:全参构造、无参构造

注意事项

Lombok会在编译时,会自动生成对应的java代码

在使用lombok时,还需要安装一个lombok的插件(新版本的IDEA中自带)

基础操作

预编译SQL

SQL注入

通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。输入 ' or '1'='1

优势

1. 性能更高

编译一次之后会将编译后的SQL语句缓存起来,后面再次执行这条语句时,不会再次编译。(只是输入的参数不同)

2. 更安全(防止SQL注入)

将敏感字进行转义,保障SQL的安全性

参数占位符

#{...}

把参数当做整体传入预编译SQL,会自动设置参数值,能够防止sql注入

使用时机:参数传递,都使用#{…},

解决SQL注入的原因:当做字符串带引号作为参数会进行转义,

${...}

拼接SQL。直接将数据拼接在SQL语句中,存在SQL注入问题

使用时机:如果对表名、列表进行动态设置时使用

注意事项:在项目开发中,建议使用#{...},生成预编译SQL,防止SQL注入安全。

1. 查询

根据主键ID查询

接口方法

@Mapper
public interface EmpMapper {
    @Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp where id=#{id}")
    public Emp getById(Integer id);
}

@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testGetById(){
        Emp emp = empMapper.getById(1);
        System.out.println(emp);
    }
}

数据封装

返回的结果中大部分字段是有值的,但是仍个字段是没有值的,而数据库中是有对应的字段值的,这是为什么呢?

原因

实体类属性名和数据库表查询返回的字段名一致,mybatis会自动封装。

如果实体类属性名和数据库表查询返回的字段名不一致,不能自动封装。

解决方案

1. 起别名

在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样

2. 结果映射

通过 @Results及@Result 进行手动结果映射

@Results({
    @Result(column = "数据库的字段名",property = "对应的属性名"),
    @Result(column = "emp_id",property = "empId"),
    ...
})

3. 开启驼峰命名

如果字段名与属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射

mybatis.configuration.map-underscore-to-camel-case=true

驼峰命名规则:  

abc_xyz    =>   abcXyz

表中字段名:abc_xyz

类中属性名:abcXyz

要使用驼峰命名前提是 实体类的属性 与 数据库表中的字段名严格遵守驼峰命名。

条件查询

接口方法

方式一

@Mapper
public interface EmpMapper {
    @Select("select * from emp " +
            "where name like '%${name}%' " +
            "and gender = #{gender} " +
            "and entrydate between #{begin} and #{end} " +
            "order by update_time desc")
    public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
}

注意事项:

1. 方法中的形参名和SQL语句中的参数占位符名保持一致

2. 模糊查询使用${...}进行字符串拼接,这种方式呢,由于是字符串拼接,并不是预编译的形式,所以效率不高、且存在sql注入风险。

方式二(解决SQL注入风险)

@Mapper
public interface EmpMapper {

    @Select("select * from emp " +
            "where name like concat('%',#{name},'%') " +
            "and gender = #{gender} " +
            "and entrydate between #{begin} and #{end} " +
            "order by update_time desc")
    public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);

}

使用MySQL提供的字符串拼接函数:concat('%' , '关键字' , '%')

执行结果:生成的SQL都是预编译的SQL语句(性能高、安全)

参数名说明

我们需要保证接口中方法的形参名和SQL语句中的参数占位符名相同。

参数名在不同的SpringBoot版本中,处理方案还不同:

springBoot的2.x版本(保证参数名一致)

SpringBoot的父工程对compiler编译插件进行了默认的参数parameters配置,使得在编译时,会在生成的字节码文件中保留原方法形参的名称,所以#{…}里面可以直接通过形参名获取对应的值

springBoot的1.x版本/单独使用mybatis(使用@Param注解来指定SQL语句中的参数名)

在编译时,生成的字节码文件当中,不会保留Mapper接口中方法的形参名称,而是使用var1、var2、...这样的形参名字,此时要获取参数值时,就要通过@Param注解来指定SQL语句中的参数名

2. 新增

接口方法

@Mapper
public interface EmpMapper {

    @Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time) values (#{username}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})")
    public void insert(Emp emp);

}

测试类

@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testInsert(){
        //创建员工对象
        Emp emp = new Emp();
        emp.setUsername("tom");
        emp.setName("汤姆");
        emp.setImage("1.jpg");
        emp.setGender((short)1);
        emp.setJob((short)1);
        emp.setEntrydate(LocalDate.of(2000,1,1));
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        emp.setDeptId(1);
        //调用添加方法
        empMapper.insert(emp);
    }
}

#{...} 里面写的名称是对象的属性名

主键返回

数据添加成功后,需要获取插入数据库数据的主键

在Mapper接口中的方法上添加一个Options注解,并在注解中指定属性useGeneratedKeys=true和keyProperty="实体类属性名"

主键返回代码实现

@Mapper
public interface EmpMapper {
    
    //会自动将生成的主键值,赋值给emp对象的id属性
    @Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time) values (#{username}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})")
    public void insert(Emp emp);

}

@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testInsert(){
        //创建员工对象
        Emp emp = new Emp();
        emp.setUsername("jack");
        emp.setName("杰克");
        emp.setImage("1.jpg");
        emp.setGender((short)1);
        emp.setJob((short)1);
        emp.setEntrydate(LocalDate.of(2000,1,1));
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        emp.setDeptId(1);
        //调用添加方法
        empMapper.insert(emp);

        System.out.println(emp.getDeptId());
    }
}

3. 更新

接口方法

@Mapper
public interface EmpMapper {
    /**
     * 根据id修改员工信息
     * @param emp
     */
    @Update("update emp set username=#{username}, name=#{name}, gender=#{gender}, image=#{image}, job=#{job}, entrydate=#{entrydate}, dept_id=#{deptId}, update_time=#{updateTime} where id=#{id}")
    public void update(Emp emp);
}

 @SpringBootTest
class SpringbootMybatisCrudApplicationTests {
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testUpdate(){
        //要修改的员工信息
        Emp emp = new Emp();
        emp.setId(23);
        emp.setUsername("songdaxia");
        emp.setPassword(null);
        emp.setName("老宋");
        emp.setImage("2.jpg");
        emp.setGender((short)1);
        emp.setJob((short)2);
        emp.setEntrydate(LocalDate.of(2012,1,1));
        emp.setCreateTime(null);
        emp.setUpdateTime(LocalDateTime.now());
        emp.setDeptId(2);
        //调用方法,修改员工数据
        empMapper.update(emp);
    }
}

4. 删除

根据主键ID删除

根据主键ID批量删除

接口方法

@Mapper
public interface EmpMapper {
    /**
     * 根据id删除数据
     * @param id    用户id
     */
    @Delete("delete from emp where id = #{id}")//使用#{key}方式获取方法中的参数值
    public void delete(Integer id);
    
}

 @Delete注解:用于编写delete操作的SQL语句

如果mapper接口方法形参只有一个普通类型的参数,#{…} 里面的属性名可以随便写,如:#{id}、#{value}。但是建议保持名字一致。

日志输入

1. 打开application.properties文件

2. 开启mybatis的日志,并指定输出到控制台

#指定mybatis输出日志的位置, 输出控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

Mybatis的XML配置文件

Mybatis的开发有两种方式

1. 注解(代码简单时使用)

@Select

@Delete

@Update

@Insert

2. XML(复杂时使用)

XML配置文件规范 (写在资源文件(resources)中用'/'当做'.'建立多级包)

如果需要实现复杂的SQL功能,建议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。

规范(mapper.java和mapper.xml文件是怎样关联的)

1. XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)

2. XML映射文件的namespace属性为Mapper接口全限定名一致

3. XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。

<select>标签:就是用于编写select查询语句的。

resultType属性,指的是查询返回的单条记录所封装的类型。

XML配置文件实现

创建XML映射文件

编写XML映射文件

xml映射文件中的dtd约束,直接从mybatis官网复制即可

https://mybatis.net.cn/

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
  <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
  </select>
</mapper>

namespace="org.mybatis.example.BlogMapper"
(表示与哪个Mapper接口文件关联,所以这里写的是Mapper接口路径)

<select id="接口中的方法名" resultType="方法的返回值类的路径"></select>
可以写<update id="接口中的方法名"></update>标签,仅有id,没有返回值类型

两个文件

接口文件

 EmpMapper.java  实现的是接口中的方法

xml文件

EmpMapper.xml  定义的 sql语句

当我们调用接口中的方法,就会执行XML文件中的sql语句(根据id找到sql语句)

MybatisX插件的使用

基于IDEA的快速开发Mybatis的插件,为效率而生

当时用aliyun创建的项目要是的方法用@Param("属性") 类型 属性

动态SQL

SQL语句会随着用户的输入或外部条件的变化而变化

一定要注意SQL结尾的分号,容易报错

动态SQL-if

<if>

用于判断条件是否成立。用test属性进行条件判断,如果条件为true,则拼接SQL。

<if test="条件表达式">
   要拼接的sql语句
</if>

条件表达式 (一般是属性)

要拼接的sql语句(一般用得字段和属性)

<where>

条件查询

动态拼接where

会自动去除子句的开头的AND或OR

<set>

更新数据

动态拼接set

会删掉额外的逗号(用于update语句中)

动态SQL-foreach

遍历deleteByIds方法中传递的参数ids集合

<foreach collection="集合名称"   
        item="集合遍历出来的元素/项" 
        separator="每一次遍历使用的分隔符"
        open="遍历开始前拼接的片段"
        close="遍历结束后拼接的片段">    
        #{id}//这里的id与item元素名称一致
 </foreach>

动态SQL-sql&include

通过<sql>标签封装到一个SQL片段,然后再通过<include>标签进行引用。

<sql>:可重用的SQL片段

<sql id="名称">
       select *
       from emp
   </sql>

<sql id="commonSelect">
     select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp
</sql>

<include>:通过属性refid,引入SQL片段

<include refid="sql的id名称"></include>或者<include refid="sql的id名称"/>

<select id="list" resultType="com.itheima.pojo.Emp">
    <include refid="commonSelect"/></include>
    <where>
        <if test="name != null">
            name like concat('%',#{name},'%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
        <if test="begin != null and end != null">
            and entrydate between #{begin} and #{end}
        </if>
    </where>
    order by update_time desc
</select>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值