MyBatis操作数据库入门补充2

其他查询操作

        多表查询

        查询sql: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}

        由于返回的数据中出现了其他表的数据,因此相应接收的Java类就要添加对应的属性.

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

        其余相关操作无需变化.

    @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);
    @Test
    void queryUserByUid() {
        System.out.println(articleInfoMapper.queryUserByUid(1));
    }

        #{}和${}

        MyBatis提供了两种赋值方式,#{}和${}.

        #{}和${}的使用

        观察对Integer类型进行赋值时的差异

    @Select("select * from userinfo where id = #{id}")
    List<UserInfo> selectUserInfoById(Integer id);

    @Select("select * from userinfo where id = ${id}")
    List<UserInfo> selectUserInfoById2(Integer id);

        观察到,在使用#{}时,sql语句是一个有占位符的预编译sql,而使用${}时是直接将参数拼接在sql语句中.

        对String类型进行赋值:

    @Select("select * from userinfo where username = #{username}")
    List<UserInfo> selectUserInfoByName(String username);

    @Select("select * from userinfo where username = ${username}")
    List<UserInfo> selectUserInfoByName2(String username);

        传递字符串时,使用#{}正常得到了结果,而使用${}出现了Badsql异常(sql语句错误),观察sql语句发现:admin没有正确加上引号.事先添加引号,观察运行结果:

    @Select("select * from userinfo where username = '${username}'")
    List<UserInfo> selectUserInfoByName2(String username);

        在手动添加引号之后,运行结果正确.

        #{}和${}的区别

        从简单的角度讲#{}和${}的区别就是预编译sql和即时sql的区别.

        首先,预编译sql的性能更好.因为一条sql语句要经过sql语法解析,sql优化,sql编译之后才会执行.预编译SQL,编译⼀次之后会将编译后的SQL语句缓存起来,后⾯再次执⾏这条语句时,不会再次编译
(只是输⼊的参数不同),省去了解析优化等过程,以此来提⾼效率.

        预编译sql可以防止sql注入,在使用${}时,可能会发生sql注入问题.在上面的根据名称查询中,如果用户输入了' or 1 = '1,那么整条sql语句就会变为select * from userinfo where username ='' or 1 ='1',由于1=1永远为true,那么此次查询将会把表中的所有信息都查出来.

    @Test
    void selectUserInfoByName2() {
        System.out.println(userInfoMapper.selectUserInfoByName2("' or 1 = '1"));
    }

        ${}的"立足之本"

        上面提到${}的性能不如#{},甚至还会出现sql注入问题,那么为什么MyBatis没有删除${}呢?

        因为${}是直接将字符串拼接在sql语句上,不会主动添加引号,那么在一下不能主动添加引号的情况下,就只能使用${}不能使用#{}.

        排序是在浏览网页时非常常见的功能,排序sql语句最后需要指定升序或降序(select * from userinfo order by id asc/desc),在这里就不能对升序或降序添加引号,就只能使用${}.

    @Select("select * from userinfo order by id ${sort}")
    List<UserInfo> selectUserInfoBySort(String sort);    
    @Test
    void selectUserInfoBySort() {
        System.out.println(userInfoMapper.selectUserInfoBySort("desc"));
    }

        如果使用#{},就会因为自动拼接引号而导致badsql异常.

        在使用${}时,为了避免sql注入需要对内容进行严格的校验.

数据库连接池

        数据库连接池负责分配,管理和释放数据库连接,它允许应⽤程序重复使⽤⼀个现有的数据库连接,⽽不是再重新建⽴⼀个.

        没有使⽤数据库连接池的情况:每次执⾏SQL语句,要先创建⼀个新的连接对象,然后执⾏SQL语句,SQL语句执⾏完,再关闭连接对象释放资源.这种重复的创建连接,销毁连接⽐较消耗资源

        使⽤数据库连接池的情况:程序启动时,会在数据库连接池中创建⼀定数量的Connection对象,当客户请求数据库连接池,会从数据库连接池中获取Connection对象,然后执⾏SQL,SQL语句执⾏完,再把Connection归还给连接池.

        这样就能减少网络开销,提升资源复用率,提升系统的性能.

        ⽬前⽐较流⾏的数据库连接池是Hikari,Druid.Spring Boot默认使用Hikari.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值