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

内容接着上一篇文章,Mybatis搭建环境(2)

先把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();;
    }
模糊查询结果.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表新插入一条用户数据。

@Test
public 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();
}
插入数据成功页面.png

更新后的表单信息.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测试方法:

@Test
public void TestDelete() throws Exception{
    SqlSession sqlSession = dataConn.getSqlSession();
    sqlSession.delete("cn.com.mybatis.dao.UserDao.deleteUser",5);
    sqlSession.commit();
    sqlSession.close(); 
}
@Test
public 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();
}
删除样例成功.png

修改样例成功.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优化要求比较高,或是项目需求或业务经常变动。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容