[spring]用MyBatis XML操作数据库 其他查询操作 数据库连接池 mysql企业开发规范 动态sql

一. MyBatis XML配置文件

MyBatis开发有两种方式:

  1. 注解
  2. XML
    使⽤Mybatis的注解⽅式,主要是来完成⼀些简单的增删改查功能. 如果需要实现复杂的SQL功能,建议使⽤XML来配置映射语句,也就是将SQL语句写在XML配置⽂件中.
    在这里插入图片描述

1. 配置链接字符串和MyBatis

添加配置:

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  # 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
  mapper-locations: classpath:mapper/**.xml

在resources路径下, 创建mapper文件, 在mapper文件下创建**.xml文件, 以xml结尾的文件
和mapper-locations: classpath:后的路径对应即可
在这里插入图片描述

2. 写持久层代码

在这里插入图片描述

方法定义Interface

在这里插入图片描述

方法实现xml

MyBatis的固定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">
<!--需要修改到上述mapper接口所对应的路径-->
<mapper namespace="com.bite.mybatis.mapper.UserInfoXmlMapper">
 

</mapper>

查询:

<?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="com.bite.demo.mapper.UserInfoXMLMapper">
    <select id="queryAllUser" resultType="com.bite.demo.model.UserInfo">
    select * from userinfo
    </select>
</mapper>
  1. < mapper> 标签: 需要指定< namespace>属性, 表示命名空间, 值为mapper接口的全限定名, 即包名.类名
  2. < select>查询标签, 用来执行数据库的查询操作
  • id : 是和接口中定义的方法名
  • resultType : 是返回的数据类型

测试

在这里插入图片描述

在这里插入图片描述

3. 增删改查

增:

 <insert id="insertUser">
        insert into userinfo (username, `password`, age, gender, phone) values
        (#{username}, #{password}, #{age}, #{gender}, #{phone})
    </insert>

在这里插入图片描述

在这里插入图片描述
返回自增id:
接口定义不变, 设置useGeneratedKeys 和keyProperty属性

 <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
        insert into userinfo (username, `password`, age, gender, phone) values
        (#{username}, #{password}, #{age}, #{gender}, #{phone})
    </insert>

 <delete id="deleteUser">
        delete from userinfo where id = #{id}
    </delete>

在这里插入图片描述

 <update id="updateUser">
        update userinfo set username = #{username} where id = #{id}
    </update>

在这里插入图片描述

和注解一样, 映射也有三种解决办法:
在这里插入图片描述
1和3和注解一样
** xml结果映射:**

 <resultMap id="BaseMap" type="com.bite.demo.model.UserInfo">
        <id column="id" property="id"></id>
        <result column="delete_flag" property="deleteFlag"></result>
        <result column="create_time" property="createTime"></result>
        <result column="update_time" property="updateTime"></result>
    </resultMap>

在这里插入图片描述

二. 开发规范(mysql)

阿里巴巴java开发手册的规范:
1.
在这里插入图片描述
2.
在这里插入图片描述
3.
在这里插入图片描述

三. 其他查询操作

1. 多表查询

  1. 准备工作
    创建一个文章表
    文章表的uid, 对应上述用户表的id
-- 创建⽂章表
DROP TABLE IF EXISTS articleinfo;
CREATE TABLE articleinfo (
 id INT PRIMARY KEY auto_increment,
 title VARCHAR ( 100 ) NOT NULL,
 content TEXT NOT NULL,
 uid INT NOT NULL,
 delete_flag TINYINT ( 4 ) DEFAULT 0 COMMENT '0正常, 1删除',
 create_time DATETIME DEFAULT now(),
 update_time DATETIME DEFAULT now() 
 ) DEFAULT charset 'utf8mb4';-- 插⼊测试数据
 
INSERT INTO articleinfo ( title, content, uid ) VALUES ( 'Java', 'Java正文', 1 );

sql: 查询id=1的作者的相关信息

select
	ta.id,
	ta.title,
	ta.content,
	ta.uid,
	tb.username,
	tb.age,
	tb.gender
from
	articleinfo ta
left join userinfo tb on
	ta.uid = tb.id
where
	ta.id = 1
  1. 实体类:
@Data
public class ArticleInfo {
    private Integer id;
    private String title;
    private String content;
    private Integer uid;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
    //用户相关信息
    private String username;
    private Integer age;
    private Integer gender;
}

  1. 接口定义:
@Mapper
public interface ArticleInfoMapper {
   @Select("SELECT ta.id,ta.title,ta.content,ta.uid,tb.username,tb.age,tb.gender " +
           "FROM articleinfo ta LEFT JOIN userinfo tb ON ta.uid = tb.id " +
           "WHERE ta.id = #{id}")
    ArticleInfo queryUserByUid(Integer id);

}
  1. 测试类:
@SpringBootTest
class ArticleInfoMapperTest {
    @Autowired
    private ArticleInfoMapper articleInfoMapper;

    @Test
    void queryUserByUid() {
        articleInfoMapper.queryUserByUid(1);
    }
}

在这里插入图片描述

2. #{} 和 ${}(面试题)

使用

  1. 传递Integer类型的参数
    #{ }:
    在这里插入图片描述
    结果:
    在这里插入图片描述我们输⼊的参数并没有在后⾯拼接,id的值是使⽤ ? 进⾏占位. 这种SQL我们称之为**“预编译SQL”**
    ${ }:
    在这里插入图片描述
    结果:
    在这里插入图片描述
    这次的参数是直接拼接在SQL语句中, 叫做即时SQL
    两种方法都不会报错
  2. 传递String类型的参数
    #{ }
    在这里插入图片描述
    在这里插入图片描述
    KaTeX parse error: Double superscript at position 213: …串作为参数时,需要添加引号' '̲, ⽤{} 不会拼接引号 ’ ‘, 导致程序报错
    就需要我们手动添加’ ’
    在这里插入图片描述
    在这里插入图片描述

区别

1. #{} 和${} 的区别就是预编译SQL和即时SQL的区别
在这里插入图片描述
预编译SQL,编译⼀次之后会将编译后的SQL语句缓存起来,后⾯再次执⾏这条语句时,不会再次编译
(只是输⼊的参数不同),省去了解析优化等过程,以此来提⾼效率
2. $ { }存在sql注入问题(重点)
SQL注⼊:是通过操作输⼊的数据来修改事先定义好的SQL语句,以达到执⾏代码对服务器进⾏攻击的⽅法。
例如, 如果使用${}, 传递的参数为’ or 1=’ 1, 返回的数据用List接收, 就会发生
在这里插入图片描述
在这里插入图片描述
输入一个用户名, 就拿到了全部用户的数据, 这是非常不安全的
可以看出:
在这里插入图片描述
⽤于查询的字段,尽量使⽤ #{} 预查询的⽅式

排序功能

排序功能就是${} 的使用场景
在这里插入图片描述
mapper实现:
在这里插入图片描述

在这里插入图片描述
可以实现逆序返回的功能
如果使用#{}:
在这里插入图片描述
使用#{}, 将参数带入到sql中, 如果是字符串类型, 会自动加上’ ', 此时sql语句就变成:
select * from userinfo order by id ‘desc’, 语法错误

那么在完成排序功能时, 使用${ }, 也是存在sql注入的问题的, 所以一般需要排序的场景, 用户并不是自己输入的, 而是通过按钮等方式, 就行选择, 就避免了sql注入的问题

在这里插入图片描述

like查询

在这里插入图片描述

三. 数据库连接池

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. Hikari : SpringBoot默认使⽤的数据库连接池
    从Spring打印的日志就可以看出来
    在这里插入图片描述
  2. Druid
    如果我们想把默认的数据库连接池切换为Druid数据库连接池,只需要引⼊相关依赖即可
 <dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>druid-spring-boot-3-starter</artifactId>
 <version>1.2.21</version>
 </dependency>

如果SpringBoot版本为2.X,使⽤druid-spring-boot-starter依赖

 <dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>druid-spring-boot-starter</artifactId>
 <version>1.1.17</version>
 </dependency>

在这里插入图片描述

四. 动态sql

1. < if > 标签

在这里插入图片描述
接口定义:
在这里插入图片描述
xml实现:

<insert id="insertUserByCondition">
        insert into userinfo (
        username, 
        password, 
        age, 
        <if test="gender != null">
            gender,
        </if>
        phone
        )
        values (
        #{username},
        #{password},
        #{age},
        <if test="gender != null">
            #{gender},
        </if>
        #{phone}
        )
    </insert>

注解实现(不推荐):
把上⾯SQL(包括标签),使⽤< script > < /script > 标签括起来就可以

@Insert("<script>" +
 "INSERT INTO userinfo (username,`password`,age," +
 "<if test='gender!=null'>gender,</if>" +
 "phone)" +
 "VALUES(#{username},#{age}," +
 "<if test='gender!=null'>#{gender},</if>" +
 "#{phone})"+
 "</script>")
 Integer insertUserByCondition(UserInfo userInfo);

在这里插入图片描述
gender是有默认值的
在这里插入图片描述

上述没有设置gender, 所以会将gender设为默认值0, 而不是null

在这里插入图片描述
在这里插入图片描述

2. < trim >标签

在这里插入图片描述

 <insert id="insertUserByCondition">
        insert into userinfo
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username != null">
                username,
            </if>
            <if test="password != null">
                password,
            </if>
            <if test="age != null">
                age,
            </if>
            <if test="gender != null">
                gender,
            </if>
            <if test="phone != null">
                phone,
            </if>
        </trim>
            values 
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username != null">
                #{username},
            </if>
            <if test="password != null">
                #{password},
            </if>
            <if test="age != null">
                #{age},
            </if>
            <if test="gender != null">
                #{gender},
            </if>
            <if test="phone != null">
                #{phone},
            </if>
        </trim>
    </insert>

在这里插入图片描述

如果不加trim时, 那么phone后面就会多一个 ,
加上trim: 自动帮我们去掉 ,
在这里插入图片描述

< where > 标签

看下⾯这个场景, 系统会根据我们的筛选条件,动态组装where条件

在这里插入图片描述
< where > 只会在子元素有内容的情况下才插⼊where⼦句,⽽且会⾃动去除⼦句的开头的AND或OR
在这里插入图片描述

 <select id="queryByCondition" resultType="com.bite.demo.model.UserInfo">
        select * from userinfo 
        <where>
            <if test="age != null">
                age = #{age}
            </if>
            <if test="gender != null">
                and gender = #{gender}
            </if>
            <if test="deleteFlag != null">
                and delete_flag = #{deleteFlag}
            </if>
        </where>
</select>

在这里插入图片描述

在这里插入图片描述

< set > 标签

需求:根据传⼊的用户对象属性来更新用户数据,可以使⽤标签来指定动态内容.
在这里插入图片描述

 <update id="updateUserByCondition">
        update userinfo
        <set>
            <if test="age != null">
                age = #{age}
            </if>
            <if test="username != null">
                username = #{username}
            </if>
            <if test="gender != null">
                gender = #{gender}
            </if>
        </set>
        where id = #{id}
</update>

在这里插入图片描述
在这里插入图片描述
以上标签也可以使⽤< trim prefix=“set” suffixOverrides=“,” > 替换

< foreach > 标签

在这里插入图片描述
需求:根据多个userid,删除用户数据
在这里插入图片描述

 <delete id="deleteByIds">
        delete from userinfo where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach> 
    </delete>

在这里插入图片描述

在这里插入图片描述

< sql > < include > 标签

在xml映射⽂件中配置的SQL,有时可能会存在很多重复的⽚段,此时就会存在很多冗余的代码
在这里插入图片描述
在这里插入图片描述

<sql id="allColumn">
        id,username,age,gender,phone,delete_flag,create_time, update_time
</sql>
<select id="queryAllUser" resultType="com.bite.demo.model.UserInfo">
        select
        <include refid="allColumn"></include>
        from userinfo
</select>   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值