快速学习MyBatis(复习)

MyBatis作用

MyBatis 是一个强大的 SQL 映射框架,它主要用于在 Java 应用程序中简化数据库交互。MyBatis 的核心功能是将 Java 对象(实体类)映射到数据库表,并且能够将 SQL 查询的结果映射回 Java 对象。这样的机制不仅提高了开发效率,还有助于维护清晰的应用程序结构。

MyBatis 的主要特点包括:

  1. SQL 映射: MyBatis 允许开发者直接编写原生 SQL 语句,并通过 XML 或注解的方式配置这些 SQL 语句。这提供了极高的灵活性,可以实现几乎所有 SQL 操作。

  2. 数据绑定: MyBatis 支持复杂的数据绑定操作。例如,可以将数据库中的行自动映射成为 Java 对象,也可以将 Java 对象中的字段自动绑定到 SQL 语句中的参数。

  3. 会话管理: MyBatis 管理数据库连接和事务的生命周期,使开发者可以专注于业务逻辑而非底层数据库操作。

  4. 插件和拦截器: MyBatis 允许开发者通过插件修改其核心行为,如查询处理、结果集处理等,增加了扩展性。

Mybatis操作

MyBatis配置文件

<!---->
<!--MyBatis 依赖:-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version> <!-- 更早的版本,与 JDK 11 兼容 -->
</dependency>
<!--MyBatis 测试依赖:-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>2.1.4</version> <!-- 更新测试依赖的版本 -->
<scope>test</scope>
</dependency>
<!--MySQL 运行时依赖:-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok 依赖:-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

实体类Pojo层

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

注解作用
@Getter/@Setter为所有属性提供get/set方法
@ToString自动生成toSting
@EqualsAndHashCode生成equals和hashcode方法
@Date@Getter+@Setter+@ToString+@EqualsAndHashCode
@NoArgsConstructor生成无参构造器
@AllArgsConstructor生成有参构造器(除了static修饰的字段以外)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class emp {
    private Integer id;
    private String username;
    private String password;
}

properties属性文件

#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接url
spring.datasource.url=jdbc:mysql://localhost:3306/db03
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234
#配置mybatis的日志, 指定输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#开启mybatis的驼峰命名自动映射开关 a_column ------> aCloumn
mybatis.configuration.map-underscore-to-camel-case=true
如何修改properties属性文件的规范
  1. 打开 IntelliJ IDEA: 启动您的 IntelliJ IDEA 编辑器。

  2. 进入设置: 在菜单栏中选择 File -> Settings(如果您使用的是 macOS,则是 IntelliJ IDEA -> Preferences)。

  3. 编辑器设置: 在设置窗口中,导航到 Editor -> File Encodings

  4. 设置全局编码: 在 Global Encoding 下拉菜单中选择 UTF-8,以设置全局默认编码。

  5. 设置项目编码: 在 Project Encoding 下拉菜单中也选择 UTF-8,确保整个项目文件的编码统一。

  6. 设置 Properties 文件编码: 向下滚动到 Default encoding for properties files,并在这里选择 UTF-8。这确保了所有 .properties 文件都将以 UTF-8 编码打开和保存。

  7. 保存设置: 点击 OKApply 保存设置。

Mapper数据访问层

@Mapper
public interface empMapper {
    @Delete("delete from emp where id= #{id}")
    public int deleteid(Integer id);
}

数据库连接池

原理类似于线程池。先创建一些连接。连接自动分配

mybatis基础操作

mybatis占位符

在Mybatis中提供的参数占位符有两种:${...} 、#{...}

#{}
执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值
使用时机:参数传递,都使用#{…}
delete from emp where id= #{id}
-- 输入16
先预编译
delete from emp where id= ?
​
${...}
delete from emp where id= #{id}
输入16
直接编译为delete from emp where id= 16
相当于直接把参数拼接到SQL语句,在运行
拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题
使用时机:如果对表名、列表进行动态设置时使用

日志输出

在Mybatis当中我们可以借助日志,查看到sql语句的执行、执行传递的参数以及执行结果。具体操作如下:

  1. 打开application.properties文件

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

#指定mybatis输出日志的位置, 输出控制台
mybatis.configuration.logimpl=org.apache.ibatis.logging.stdout.StdOutImpl
==>  Preparing: delete from emp where id= ?
==> Parameters: 15(Integer)
<==    Updates: 1

但是我们发现输出的SQL语句:delete from emp where id = ?,我们输入的参数15并没有在后面拼接,id的值是使用?进行占位。那这种SQL语句我们称为预编译SQL。

预编译SQL

预编译SQL有两个优势:

  1. 性能更高

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

性能更高:预编译SQL,编译一次之后会将编译后的SQL语句缓存起来,后面再次执行这条语句
时,不会再次编译。(只是输入的参数不同)
更安全(防止SQL注入):将敏感字进行转义,保障SQL的安全性。
SQL注入

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

由于没有对用户输入进行充分检查,而SQL又是拼接而成,在用户输入参数时,在参数中添加一些
SQL关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击。

sql注入攻击

-- 用户名随便,密码' or '1'='1
select count(*) from emp where username='asdad'and password='' or '1'='1';

如果使用预编译,会把代码预编译,在插入内容

select count(*) from emp where username=? and password=?;

删除

public interface empMapper {
    @Delete("delete from emp where id= #{id}")
    public int deleteid(Integer id);//删除成功返回1,失败0
}
@Delete注解:用于编写delete操作的SQL语句

插入

@Insert("insert into emp(username, password, 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);

返回主键

//会自动将生成的主键值,赋值给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);

更新修改

@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);

查询

数据封装
起别名查询
@Select("select id, username, password, name, gender, image, job,entrydate, " +
            //给带_的起一个和emp实体类属性一样的别名
            "dept_id AS deptId, create_time AS createTime, update_time ASupdateTime " +
            "from emp " +"where id=#{id}")
    public Emp getById(Integer id);
手动映射(繁琐)
@Results({
     @Result(column = "dept_id",property = "deptId")  ,
     @Result(column = "create_time",property = "createTime")   ,
     @Result(column ="update_time",property = "updateTime")
    })
    @Select("select * from emp where id=#{id}")
    public emp getbyid(Integer id);
开启mybatis开启驼峰的设置(建议)

properties属性文件配置

#开启mybatis的驼峰命名自动映射开关
mybatis.configuration.map-underscore-to-camel-case=true

代码例子

@Select("select * from emp where id=#{id}")
public emp getbyid(Integer id);
条件查询
concat拼接
concat('%',#{name},'%')
//    @Select("select * from emp where name like '%张%' and gender=1 and entrydate between '2010-01-01' and '2020-01-01'" +
//            " order by update_time desc ;")
//    public List<emp> list();
​
    //为什么不使用'%#{name}%',因为#{name}最后要预编译为?,如果?出现在了''就会被当作字符串。
    //如果必须使用#可以通过concat进行拼接
    @Select("select * from emp where name like concat('%',#{name},'%') and gender=#{gender} and entrydate between #{begin} and #{end}" +
            " order by update_time desc ;")
​
//    @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);
@Test
    public void selectid(){
        List<emp> list=empmapper.list("张", (short) 1, 
                                      LocalDate.of(2010,1,1),LocalDate.of(2020,1,1));
        
        list.stream().forEach(System.out::println);
    }

XML映射文件

使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。

选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队。 换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换。

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

  • XML映射文件的namespace属性为Mapper接口全限定类名一致。

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

Mapper接口

@Mapper
public interface empMapper {
    public List<emp> list(String name, short gender, LocalDate begin,LocalDate end);
}

XML映射文件

<!--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接口的全类名-->
<mapper namespace="com.example.Mapper.empMapper">
    <!--id=方法名-->
    <!--resultType(翻译为:结果的类型)
           但是resultType指的是输出内容单条记录所封装的类型。
                虽然下面代码输出的是一个集合,但是单条记录所封装的是emp,所以                                                                         resultType="com.example.Pojo.emp"-->
    <select id="list" resultType="com.example.Pojo.emp">
        select * from emp where name like concat('%',#{name},'%') and gender=#{gender}
            and entrydate between #{begin} and #{end} order by update_time desc
    </select>
</mapper>
为什么需要有三条规范

是为了让方法能找到sql语句。

MyBatis动态SQL

动态SQL:

随着用户输入或外部条件的变化而变化的SQL语句称为SQL语句,称为动态SQL

 <select id="list" resultType="com.example.Pojo.emp">
        select * from emp 
           where 
                namelike concat('%',#{name},'%') 
                      and gender=#{gender}
                         and entrydate between #{begin} and #{end}
           order by update_time desc
    </select>
这个SQL必须几个条件同时输入才能查询,如果想要用一个条件查询就不行了

动态SQL-if

<if test="..">..</if>:用于判断条件是否成立,使用test属性进行条件判断,如果为true,则拼接SQL语句
<where> </where>
<set>用于删除字段,原理同<where>类似
<select id="list" resultType="com.example.Pojo.emp">
        select * from emp
     <!--如果使用where会出错
     错误1.如果第一条不成立,第二条成立会导致SQL语句为select * from emp where and gender=?
     错误2.如果都不成立,会导致SQL语句出现select * from emp where  order by update_time desc -->
    <where>
        <!--
        1.自动去除条件前面的and或or等连接符
        2.根据子标签动态生成where关键字,如果里面条件都不成立不会生成where关键字-->
        <if test="name != null">
            name like concut('%',#{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>

动态SQL-foreach

foreach遍历

<!--批量删除员工(15,16,17)-->
    <delete id="deleteid">
        delete from emp where id in
           <!--
           collection:要遍历的集合
           item:遍历出来的元素
           separator:遍历出来的元素使用什么进行分隔
           open:遍历开始前拼接的SQL片段
           close:遍历结束后拼接的SQL片段
           -->
          <!--(15,16,17)-->
         <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
         </foreach>
         <!--运行结果==>  Preparing: delete from emp where id in ( ? , ? , ? )
                         Parameters: 15(Integer), 16(Integer), 17(Integer)-->
    </delete>

动态SQL-sql和include

xml有多个sql的重复代码,可以把他们放到一个标签,使用的时候在抽取

存放

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

引用

<select id="list" resultType="com.example.Pojo.emp">
    <!--抽取代码
             refid=需要引用的标签的id名
             -->
       <include refid="commonSelect"/>
    <where>
        <if test="name != null">
            name like concut('%',#{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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值