专栏首页理想二旬不止MyBatis快速上手增删改查

MyBatis快速上手增删改查

引言-絮絮叨叨

作为一个快乐的小码农,在每一个阶段往往都在重复写着不同版本的,学生管理,用户管理,注册登录,从 JavaSE 的控制台版,或者 GUI 版,再到 JavaWeb的 JSP版,再到纯粹使用 HTML 作为前端展示的版本,以及使用一个更新的技术,在此其中,我们用过 txt 做数据库,用 XML 也可以,到现在常用的 MySQL,增删改查一直是我们必不可少的一部分内容,即使你不懂原理,即使你对这个技术的理解不是很深刻,拿出你的增删改查,噼里啪啦就是一段乱敲,好歹还是能让你着手先做起来(当然,对技术的理解还是很重要的),今天就和大家聊一聊 MyBatis 这门技术的 CURD (增删改查)

优化测试方法

在测试方法中,读取配置文件,生产 SqlSession,释放资源等等,在每一测试方法的时候,都是重复的,所以我们完全可以提出出这一部分,防止大量的重复代码

@Before
    public  void init() throws Exception{
        //读取配置文件
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //创建SqlSessionFactory工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

        //使用工厂生产SqlSession对象
        sqlSession= factory.openSession();
        //使用SqlSession创建Mapper接口的代理对象
        userMapper = sqlSession.getMapper(UserMapper.class);
    }
 @After
    public void destroy() throws Exception{
        sqlSession.close();
        inputStream.close();
    }

在这两个方法上增加 @Before 和 @Aftrer 注解,就可以保证,init() 和 destory() 这两个方法,分别在我们真正被测试的方法的前后执行

(一) 增添操作

(1) 编写代码

首先,在 UserMapper 接口中 增加对应的方法

public interface UserMapper {
    /**
     * 增加用户
     * @param user
     */
    void addUser(User user);
}

接着,在SQL映射文件中,增加新增的映射配置,这些有关内容放在 <insert></insert>标签对中,具体代码如下

<insert id="addUser" parameterType="cn.ideal.domain.User">
    insert into                          user(username,telephone,birthday,gender,address)values(#{username},#   {telephone},#{birthday},#{gender},#{address})
</insert>

(2) 说明:

1、id 属性,自然是对应的方法名,而由于这里,我们并不需要拿到返回信息,所以这里并没有返回参数 resultType,而方法中的参数又为一个 JavaBean 类,也就是User实体类,所以需要在标签属性中,添加一个 parameterType 属性,其中需要指定这个实体类

2、在文本中书写插入的SQL语句,由于实体类中已经快捷生成了对应的 get set 方法,所一可以使用 #{}的方式代表对应的值

3、提示,数据库中id为自增,所以并不需要设置 id

(3) 注意:

由于添加是更新类的语句,所以在执行插入语句后,需要提交事务,也就是执行对应的 commit方法,以提交更新操作,若没有这一句,即使不会报错,也无法正常存入,会被回滚,且这个id被占用

(4) 测试代码:

/**
     * 测试新增用户
     * @throws Exception
     */
    @Test
    public void testUpdateUser() throws Exception{
        User user = new User();
        user.setId(17);
        user.setUsername("修改");
        user.setTelephone("18899999999");
        user.setBirthday(new Date());
        user.setGender("女");
        user.setAddress("广州");

        //执行方法
        userMapper.updateUser(user);

    }

(5) 执行结果:

控制台:

(6) 获取新增用户的id值

首先对于 MySQL自增主键来说,在执行 insert语句之前,MySQL 会自动生成一个自增主键,insert执行后,通过 SELECT LAST_INSERT_ID() 可以获取这条刚插入记录的自增主键

在 SQL 映射配置文件中,需要借助 <selectKey></selectKey> 标签,有一个属性比较特殊,order 属性,它代表着相对于插入操作的执行时间,before-之前,after-之后

注:该标签插入到 <select></select>

<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
    SELECT LAST_INSERT_ID();
</selectKey>

测试一下

@Test
public void testAddUser() throws Exception{
    User user = new User();
    user.setUsername("增加");
    user.setTelephone("12266660000");
    user.setBirthday(new Date());
    user.setGender("男");
    user.setAddress("珠海");
    System.out.println("执行插入前" + user);
    //执行方法
    userMapper.addUser(user);
    System.out.println("执行插入后" + user);
}

执行效果

(二) 修改操作

(1) 编写代码

在 UserMapper 接口中增加修改方法

public interface UserMapper {
    /**
     * 更新用户
     * @param user
     */
    void updateUser(User user);
}

在 SQL 映射文件中增加语句,内容包括在 <update></update> 中,需要注意的基本与添加操作是一致的

<update id="updateUser" parameterType="cn.ideal.domain.User">
    update user set username=#{username},telephone=#{telephone},birthday=#{birthday},gender=#{gender},address=#{address} where id=#{id}
</update>

(2) 测试代码

/**
     * 测试新增用户
     * @throws Exception
     */
    @Test
    public void testAddUser() throws Exception{
        User user = new User();
        user.setUsername("增加");
        user.setTelephone("12266668888");
        user.setBirthday(new Date());
        user.setGender("女");
        user.setAddress("成都");

        //执行方法
        userMapper.addUser(user);

    }

(3) 执行效果

(三) 删除操作

(1) 编写代码

接口中增加删除方法

public interface UserMapper {
    /**
     * 删除用户
     * @param uid
     */
    void deleteUser(Integer uid);
}

在SQL映射文件中,使用 <delete></delete> 标签对进行内容的书写,需要注意的是,由于我们传入的参数是一个 Integer类型的用户id,所以参数类型的值为 parameterType

<delete id="deleteUser" parameterType="java.lang.Integer">
    delete from user where id=#{id}
</delete>

(2) 测试代码

/**
 * 测试删除用户
 * @throws Exception
 */
@Test
public void testDeleteUser() throws Exception{
    //执行方法
    userMapper.deleteUser(17);
}

(3) 执行效果

(四) 模糊查询

由于查询全部非常简单,这里就不展示了,基本流程都是一样的

(1) 编写代码

在 UserMapper 接口中编写方法

public interface UserMapper {
    /**
     * 通过姓名模糊查询
     * @param username
     * @return
     */
    List<User> findByName(String username);
}

在 SQL 映射文件中新增查询语句

<select id="findByName" parameterType="java.lang.String" resultType="cn.ideal.domain.User">
    select * from user where username like #{username}
</select>

(2) 测试代码

/**
 * 测试模糊查询
 * @throws Exception
 */
@Test
public void testFindByName() throws Exception{
    List<User> users = userMapper.findByName("%张%");
    for (User user : users){
        System.out.println(user);
    }
}

(3) 注意

在使用模糊查询的时候,我们需要在查询条件的两侧拼接两个 “%” 字符串,这个时候有两种解决方案,一种就是像在我上述代码中,在测试时将字符串补充完整,还有一种方式就是 使用 ${} ,它在 SQL配置文件中代表一个 “拼接符号” ,也就是说可以这样写 SQL语句

select * from user where username like '%{value}'

可接受的类型有,普通类型(此情况下{}内部只能写value),JavaBean,HashMap

但是使用%{} 拼接字符串的时候,会引起 SQL注入,所以不是很推荐使用

(4) 执行效果

(五) 自定义包装类作为查询条件

Mapper 的输入映射样例中,我们对于基本数据类型和基本数据包装类,都有了一定的了解,而下面我们来聊一聊关于相对复杂的一种情况,那就是自定义包装类

先讲一个需求:还是关于用户的查询,但是查询条件复杂了一些,不仅仅局限于用户的信息,而且可能还包括订单,购物车,或者与用户一些行为相关的信息,那么如何实现这样一种需求呢?

那我们想,可不可以,在 User 类中增加一些我们需要的信息

  • 从代码的角度来看,在 User 中添加的字段与数据库不一定能对应起来,在原来的基础上做修改,就会影响 User 作为数据库映射对象的功能,所以我们可以创建一个 UserInstance 类,继承 User类就可以在其中为某些业务添加一些不属于数据库的字段了

(1) 定义包装类

package cn.ideal.domain;

public class QueryUserVo {
    private UserInstance userInstance;

    public UserInstance getUserInstance() {
        return userInstance;
    }

    public void setUserInstance(UserInstance userInstance) {
        this.userInstance = userInstance;
    }

    //其他查询条件,例如订单,购物车等等
}

(2) 配置 Mapper 文件

我们这里使用用户的性别以及对姓名的模糊查询,来写SQL 当然,你也可以自己通过别的信息写SQL

<select id="findUserByVo" parameterType="cn.ideal.domain.QueryUserVo" resultType="cn.ideal.domain.UserInstance">
    select * from user where user.gender=#{userInstance.gender} and user.username like #{userInstance.username}
</select>

在QueryUserVo 中,封装的是查询信息的各种对象,为什么上述代码可以直接通过 userInstance.gender 直接取出对应的属性,这种方式叫做 OGNL 表达式,在类中 我们的写法通常是 user.getUsername 但在写法上,OGNL 表达式将get给省略了

(3) 测试代码

/**
 * 包装对象作为查询参数
 * @throws Exception
 */
@Test
public void testFindUserByVo() throws Exception{
    //创建包装对象,设置查询条件
    QueryUserVo queryUserVo = new QueryUserVo();
    UserInstance userInstance = new UserInstance();
    userInstance.setGender("女");
    userInstance.setUsername("%张%");
    queryUserVo.setUserInstance(userInstance);

    //调用 UserMapper 的方法
    List<UserInstance> userInstances 
          = userMapper.findUserByVo(queryUserVo);
    for (UserInstance u : userInstances){
        System.out.println(u);
    }
}

(4) 执行效果

本文分享自微信公众号 - 理想二旬不止(ideal-20),作者:BWH_Steven

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-02-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • (八) SpringBoot起飞之路-整合Shiro详细教程(MyBatis、Thymeleaf)

    姗姗来迟的第八篇,这一篇姑且认为 Springboot 的基础整合部分已经算结束了,或许还会写一些相关的,还有MySQL没有重新整理的,Linux相关的,以及我...

    BWH_Steven
  • MyBatis配置动态SQL语句

    在 MyBatis 的 SQL映射文件中,有时候需要根据一些查询条件,来选择不同的SQL语句,如果每一个场景都重写SQL,很显然效率没有很高,而 MyBatis...

    BWH_Steven
  • MyBatis进阶 -【多表查询】的正确打开方式

    经过了 MyBatis 基本增删改查的学习,而在实际的项目中,我们往往会接触到多表的操作,什么是多表呢, 在实际生活中,每个实体之间往往是存在关系的,而我们的项...

    BWH_Steven
  • ThinkPHP之数据库操作

    数据库的操作是由模型来管理的,模型类的作用大多数情况是操作数据表的,如果按照系统的规范来命名模型类的话,大多数情况下是可以用模型的名字自动对应数据表的。 模型类...

    benny
  • 数据库MySQL-设计规范

    a、采用26个英文字母(区分大小写)和0-9的自然数(经常不需要)加上下划线’_'组成; b、命名简洁明确(长度不能超过30个字符); c、例如:user,...

    cwl_java
  • Clojure 学习入门(4)—— 字符串

    一、创建 函数str: 函数 (str) 接受任意数量的参数。如果参数不是字符串则将其转换为字符串,返回创建的新字符串。如果没有参数或为nil,则返回空字符串...

    阳光岛主
  • C# 使用SqlBulkCopy类批量复制大数据

    特别注意  sqlbulkcopy.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].Col...

    跟着阿笨一起玩NET
  • django自带用户认证模块笔记

    注意,这里在执行时直接就保存到数据库了,并且,密码是加密过的文本。另外,数据是存储在django ORM自动生成的auth_user表中了,并不是用户自定义的表...

    休辞醉倒
  • 在 Laravel 中使用 Event 特性优化代码结构

    在 Laravel 里,有些事件是由她自动发起的,例如 Model 的 create、save、 update 或者是 delete 操作时,她会分别发起相应的...

    overtrue
  • python查询mysql,返回json

    py3study

扫码关注云+社区

领取腾讯云代金券