为了账号安全,请及时绑定邮箱和手机立即绑定

Mybatis入门程序数据操作(3)

标签:
MySQL

先把dao层的接口给出来,和UserMapper.xml中的mapper标签的namespace属性对接。

package cn.com.mybatis.dao;import cn.com.mybatis.po.User;public interface UserDao {    User findUserById(int id);    User findUserByUsername(String username);    int insertUser(User user);    int deleteUser(int id);    User updateUserName(String username);
}

1. 模糊查询样例

要对数据库中User表的数据进行模糊查询,需要通过匹配名字的某个字来查询该用户,首先在UserMapper.xml文件中配置SQL映射:

<!--根据用户姓名进行模糊查询--><select id="findUserByUsername" parameterType="java.lang.String" resultType="cn.com.mybatis.po.User">
    SELECT * FROM USER WHERE username LIKE '%${value}'</select>

这里“${}”符号表示拼接SQL串,将收到的参数内容不加任何修饰地拼接在SQL中,在“${}”中只能使用value代表其中的参数。然而在Web项目中,如果没有防范SQL注入的机制,要谨慎使用“${}”符号拼接SQL语句串,因为这可能会引起SQL注入的风险。
然后在MyBatisTest测试类中写一个新的测试方法TestFuzzySearch,来查询所有名称中含有“丽”字的用户信息。

@Test
    public void TestFuzzySearch() throws IOException{
        SqlSession sqlSession = dataConn.getSqlSession();
        List<User> userList = sqlSession.selectList("cn.com.mybatis.dao.UserDao.findUserByUsername","丽");        for(User user : userList){
            System.out.println("姓名:"+user.getUsername());
            System.out.println("性别:"+user.getGender());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            System.out.println("生日:"+sdf.format(user.getBirthday()));
            System.out.println("所在地:"+user.getProvince()+user.getCity());
        }
        sqlSession.close();;
    }

webp

模糊查询结果.png

2. 新增样例

要对数据库中User表进行新增数据,在UserMapper.xml文件中配置SQL映射:

<!--在表中新增数据信息--><insert id="insertUser" parameterType="cn.com.mybatis.po.User">
    INSERT INTO USER(username, password, gender, birthday, email, province, city)
      VALUE (#{username}, #{password}, #{gender}, #{birthday,jdbcType=DATE}, #{email}, #{province}, #{city})</insert>

在测试类MyBatisTest中添加名为TestInsert方法,向User表新插入一条用户数据。

@Testpublic void TestInsert() throws Exception{
    SqlSession sqlSession = dataConn.getSqlSession();
    User user = new User();
    user.setUsername("孙佳佳");
    user.setGender("男");
    user.setPassword("5555");
    user.setEmail("5555@126.com");
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    user.setBirthday(sdf.parse("1991-02-16"));
    user.setProvince("湖北省");
    user.setCity("武汉市");
    sqlSession.insert("cn.com.mybatis.dao.UserDao.insertUser",user);
    sqlSession.commit();
    sqlSession.close();
}

webp

插入数据成功页面.png


webp

更新后的表单信息.png

如果想在插入之后不执行查询语句而立即获取id信息,有两种方法,这里针对Mysql为例:


  1. 通过Mysql的函数SELECT LAST_INSERT_ID()来获取刚刚插入记录的自增主键(即取出最后一个主键)。
    这里order参数表示该SQL函数相对于insert语句的执行时间,有BEFORE和AFTER。这里程序执行完insert之后,就可以在测试类中,从user对象中直接拿到该id的信息(取出的主键信息会放置在输入参数user对象中)。

<!--在表中新增数据信息--><insert id="insertUser" parameterType="cn.com.mybatis.po.User">
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
        SELECT LAST_INSERT_ID()    </selectKey>
    INSERT INTO USER(username, password, gender, birthday, email, province, city)
      VALUE (#{username}, #{password}, #{gender}, #{birthday,jdbcType=DATE}, #{email}, #{province}, #{city})</insert>

  1. 在insert标签中添加属性“useGenerateKeys”和“keyProperty”,其中userGeneratedKeys表示使用自增主键,而keyProperty是Java对象的属性名。

<!--在表中新增数据信息--><insert id="insertUser" parameterType="cn.com.mybatis.po.User"
    useGeneratedKeys="true" keyProperty="id">
    INSERT INTO USER(username, password, gender, birthday, email, province, city)
      VALUE (#{username}, #{password}, #{gender}, #{birthday,jdbcType=DATE}, #{email}, #{province}, #{city})</insert>

进行完上面的配置后,MyBatis执行完insert语句后,会自动将自增长id值赋给对象User的属性id,然后在逻辑处理层就可以通过User的get方法获得该id。

3. 删除与修改样例

对于删除和修改,同样需要在UserMapper.xml配置文件中编写相关的SQL配置:

<!--删除用户--><delete id="deleteUser" parameterType="java.lang.Integer">
    DELETE FROM USER WHERE id=#{id}</delete><!--修改用户--><update id="updateUserName" parameterType="cn.com.mybatis.po.User">
    UPDATE USER SET username=#{username} where id=#{id}</update>

在MyBatisTest测试类中添加TestDelete和TestUpdate测试方法:

@Testpublic void TestDelete() throws Exception{
    SqlSession sqlSession = dataConn.getSqlSession();
    sqlSession.delete("cn.com.mybatis.dao.UserDao.deleteUser",5);
    sqlSession.commit();
    sqlSession.close(); 
}@Testpublic void TestUpdate() throws Exception{
    SqlSession sqlSession = dataConn.getSqlSession();
    User user = new User();
    user.setId(4);
    user.setUsername("孙丽");
    sqlSession.update("cn.com.mybatis.dao.UserDao.updateUserName", user);
    sqlSession.commit();
    sqlSession.close();
}

webp

删除样例成功.png


webp

修改样例成功.png

到此Mybatis的基本入门操作就完成了,下面补充一下注意的事项:

  • 关于parameterType:
    在执行SQL配置时,需要指定输入参数的类型。parameterType就是用来在SQL映射文件指定输入参数类型的。使用parameterType可以指定参数为基本数据类型(如 int、float等)、包装数据类型(Integer类、Double类)以及用户编写的JavaBean封装类。

  • 关于resultType:
    在加载SQL配置,并绑定制定输入参数和运行SQL之后,会得到数据库返回的相应结果,此时使用resultType来指定数据库返回的信息对应Java的数据类型。输出参数的类型为基本数据类型(如 int、float等)、包装数据类型(Integer类、Double类)以及用户自己编写的JavaBean的封装类。

  • 关于“#{}”:
    在SQL配置文件中,输入参数需要占位符来标识对应的位置。在传统的JDBC的编程中,占位符用"?"来表示,然后在加载SQL之前按照"?"的位置设置参数。在MyBatis中也是一种占位符,它接受输入参数,在大括号中编写参数名称来接受对应参数。“#{}”接受的可以是简单类型、普通JavaBean或者HashMap。里面可以写value或者其他名称。若接受的是JavaBean,它通过OGNL读取对象中的属性值,通过“属性1.属性2.属性3等”的方式获取对象属性值。

  • 关于“${}”:
    在SQL配置中,有时需要拼接SQL语句。例如在模糊查询时,就需要在查询条件的两侧拼接两个“%”字符串,这时“#{}”就不行。在MyBatis中,“${}”在SQL配置文件中表示的是一个“拼接符号”,可以在原有SQL语句上拼接新的符合SQL语法的语句。单用“${}”会引起SQL注入,慎用。另外,当接受简单类型时,“${}”中只能写“value”,而不能写其他名称。其他内容同上。

注意 ${} 和 #{} 的区别:

动态 sql 是 mybatis 的主要特性之一,在 mapper 中定义的参数传到 xml 中之后,在查询之前 mybatis 会对其进行动态解析。mybatis 为我们提供了两种支持动态 sql 的语法:#{} 以及 ${}。

  • ${}哪边都能使用,只是存在sql注入风险,相当于直接拼接字符串,不对参数做任何处理。

  • #{}会进行预编译,对参数进行处理,防止注入。

<!--在下面的语句中,如果 username 的值为 zhangsan,则两种方式无任何区别:-->select * from user where name = #{name};
select * from user where name = ${name};<!--解析出来的结果都是如下:-->select * from user where name = 'zhangsan';
  • 但是 #{} 和 ${} 在预编译中的处理是不一样的。#{} 在预处理时,会把参数部分用一个占位符 ? 代替,变成如下的 sql 语句:

elect * from user where name = ?;
  • 而 ${} 则只是简单的字符串替换,在动态解析阶段,该 sql 语句会被解析成:

select * from user where name = 'zhangsan';
  • 以上,#{} 的参数替换是发生在 DBMS 中,而 ${} 则发生在动态解析过程中。
    那么,在使用过程中我们应该使用哪种方式呢?
    答案是,优先使用 #{}。因为 ${} 会导致 sql 注入的问题。看下面的例子:

select * from ${tableName} where name = #{name}<!--若表名为user; delete user; 则动态解析之后 sql 如下:-- -->select * from user; delete user; -- where name = ?;

之后的语句被注释掉,而原本查询用户的语句变成了查询所有用户信息+删除用户表的语句,会对数据库造成重大损伤,极大可能导致服务器宕机

  • 既然这样那为什么还要用${}呢。
    因为使用#{}存在一个不足,当参数为字符串时会加上'',这就导致某些情况下sql失效。
    SELECT * FROM #{tableName},当使用#{}传入参数user,sql就会变成
    SELECT * FROM 'user'. 这样就会报错查询不到数据

参考文章: Mabatis中#{}和${}的区别mybatis #{}与${}使用场景

  • 关于“selectOne”与“selectList”:
    它们都属于SqlSession类提供的方法,在使用查询语句时,如果查询的数据只有一条数据,那么可以使用“selectOne”方法进行查询;如果查询的数据可能多于一条,那么可以使用“selectList”方法进行查询。

  • MyBatis与Hibernate区别:
    MyBatis的特点就是以SQL语句为核心的不完全的ORM(关系型映射)框架。与Hiberna相比,Hibernate的学习成本比较高,而SQL语句并不需要开发人员完成,只需调用相关API即可。这对于开发效率是一个优势,但是缺点时没办法对SQL语句进行优化和修改。而MyBatis虽然需要开发人员自己配置SQL语句,MyBatis来实现映射关系,但是这样的项目可以适应经常变化的项目需求。所以,使用MyBatis的场景是:对SQL优化要求比较高,或是项目需求或业务经常变动。



作者:LeaveStyle
链接:https://www.jianshu.com/p/fab9a7415b65


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消