MyBatis②CRUD和模糊查询

 

3、CRUD

3.1、Mapper映射

常用属性

  • namespace:命名空间,用于绑定接口;
  • select标签:匹配SQL查询语句。CRUD操作分别匹配不同的标签,如果误用可能会报错。
  • id:方法名,要与接口中方法名一致;
  • resultType:返回结果类型,要填写全类名;
  • parameterType:参数类型,一般是pojo类的全类名或基本数据类型。
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">
    <select id="" resultType="" parameterType="">
		/*SQL语句*/
    </select>
</mapper>

3.2、CRUD

3.2.1、select

查询的返回值一般为pojo类,增删改的返回值一般为int(受影响行数)或boolean(是否成功)。

Mapper接口

/** 
* 根据ID查询用户 
* 
* @param id 用户ID 
* @return 用户 
*/
User getUserById(int id);

Mapper.xml

这里传递的参数是基本数据类型,则#{参数值}填写参数名。

<select id="getUserById" resultType="indi.jaywee.pojo.User" parameterType="int">
    select *    
    from mybatis.user
    where id = #{id}
</select>

JUnit测试

@Test
public void testGetUserById() {
    // 获取SqlSession实例
    SqlSession sqlSession = MyBatisUtils.getSqlSession();

    // 获取Mapper
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 执行方法
    User user = mapper.getUserById(2);

    System.out.println(user);

    // 关闭连接
    sqlSession.close();
}

3.2.2、insert

注意:

  1. 增删改操作,需要提交事务;
  2. Mapper.xml中,增加操作对应的是insert标签

Mapper接口

/** 
* 新增用户 
* 
* @param user 待新增用户 
* @return 受影响行数 
*/
int insertUser(User user);

Mapper.xml

这里传入的参数是User,而不是基本数据类型,则#{参数值}填写User类中的属性名。

<insert id="insertUser" parameterType="indi.jaywee.pojo.User">
    insert into mybatis.user(name, password)
    value (#{name}, #{password})
</insert>

JUnit

@Test
public void testInsertUser() {
    // 获取SqlSession实例
    SqlSession sqlSession = MyBatisUtils.getSqlSession();

    // 获取Mapper
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 执行方法
    int i = mapper.insertUser(new User("demo", "123456"));

    if (i > 0) {
        System.out.println("插入" + i + "行数据");
    }

    // 提交事务!!
    sqlSession.commit();

    // 关闭连接
    sqlSession.close();
}

注意:报错org.apache.ibatis.binding.BindingException: Mapper method 'indi.jaywee.dao.UserMapper.insertUser attempted to return null from a method with a primitive return type (int)。说明Mapper.xml中可能使用了select标签,正确的是使用insert标签。

3.2.3、remove

注意:

  1. 增删改操作,需要提交事务;
  2. Mapper.xml中,删除操作对应的是delete标签

Mapper接口

/** 
* 通过ID删除用户 
* 
* @param id 用户ID 
* @return 受影响行数 
*/
int deleteUserById(int id);

Mapper.xml

这里传递的参数是基本数据类型,则#{参数值}填写参数名。

<delete id="deleteUserById" parameterType="int">
    delete    from mybatis.user
    where id = #{id}
</delete>

JUnit

@Test
public void testDeleteUserById() {
    // 获取SqlSession实例
    SqlSession sqlSession = MyBatisUtils.getSqlSession();

    // 获取Mapper
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 执行方法
    int i = mapper.deleteUserById(10);

    if (i > 0) {
        System.out.println("删除" + i + "行数据");
    }

    // 提交事务!!
    sqlSession.commit();

    // 关闭连接
    sqlSession.close();
}

3.2.4、update

注意:

  1. 增删改操作,需要提交事务;
  2. Mapper.xml中,更新操作对应的是update标签

Mapper

/** 
* 更新用户 
* @param user 用户 
* @return 受影响行数 
*/
int updateUser(User user);

Mapper.xml

这里传入的参数是User,而不是基本数据类型,则#{参数值}填写User类中的属性名。

<update id="updateUser" parameterType="indi.jaywee.pojo.User">
    update mybatis.user
    set name=#{name},
    password=#{password}
    where id = #{id}
</update>

JUnit

@Test
public void testUpdateUser() {
    // 获取SqlSession实例
    SqlSession sqlSession = MyBatisUtils.getSqlSession();

    // 获取Mapper
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 执行方法
    int i = mapper.updateUser(new User(8, "ppp", "2424"));

    if (i > 0) {
        System.out.println("更新" + i + "行数据");
    }

    // 提交事务!!
    sqlSession.commit();

    // 关闭连接
    sqlSession.close();
}

3.3、Map参数的使用

当实体类的属性(数据库中的表的字段)或参数过多时,应当考虑使用Map。

将Map<String,Object>作为方法的参数,以更新用户为例。

Mapper

/** 
* 更新用户 
* @param map 参数 
* @return 受影响行数 
*/
int updateUser1(Map<String, Object> map);

Mapper.xml

这里传入的参数是map,则#{参数值}填写map中键值对的Key。

<update id="updateUser1" parameterType="map">
    update mybatis.user
    set name=#{newName},
    password=#{newPassword}
    where id = #{id};
</update>

JUnit

注意:map的KeyMapper.xml中的参数值一致。

@Test
public void testUpdateUser1() {
    // 获取SqlSession实例
    SqlSession sqlSession = MyBatisUtils.getSqlSession();

    // 获取Mapper
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);


    Map<String, Object> map = new HashMap<>();

    map.put("id",1);
    map.put("newName","administrator");
    map.put("newPassword","admin123");


    // 执行方法
    int i = mapper.updateUser1(map);

    if (i > 0) {
        System.out.println("更新" + i + "行数据");
    }

    // 提交事务!!
    sqlSession.commit();

    // 关闭连接
    sqlSession.close();
}

3.4、再次说明

  1. 增删改操作,需要提交事务;
  2. Mapper.xml中,CRUD操作对应的不同标签;
  3. 接口方法的参数问题
    • 参数是基本数据类型:在Mapper.xml中的#{参数值}填写参数列表中的参数名;
    • 参数是POJO类:在Mapper.xml中的#{参数值}填写pojo类的属性名;
    • 参数是map:在Mapper.xml中的#{参数值}填写map中键值对的Key。

4、模糊查询

只要涉及到模糊查询,就离不开SQL注入问题。

4.1、SQL注入问题

SQL注入攻击是指恶意拼接SQL作为参数,传递给Web服务器,进而传给数据库服务器以执行数据库命令,获取数据库的信息以及提权。

举例:登录需要验证用户名和密码,SQL语句和参数拼接:

"SELECT * FROM user WHERE name = '" 
    + name 
    + "' AND psw = '" 
    + psw + "'";

SQL注入:

String name = "' or '1=1"
String psw = "' or '1=1"

name和psw被恶意注入,导致SQL语句为

SELECT * 
FROM user 
WHERE `name` = '' or '1=1' 
	AND `psw` = '' or '1=1'

此SQL语句相当于SELECT * FROM user,即不需要name和psw,通过SQL注入查出了所有用户。

4.2、解决SQL注入问题

编写SQL时,如果采取SQL和参数拼接的方式,很容易被SQL注入。

如何解决呢?使用占位符?来替代参数部分就可以了。

4.3、JDBC解决SQL注入问题

JDBC编写SQL的2种方式:

  • 拼接字符串:会将接收到的参数内容不加任何修饰符,拼接在 SQL 中。会引起SQL注入问题。

    例子:可以参照上面的例子。

  • 占位符:接收到的参数中如果有特殊符号,将会被转义。可以解决SQL注入问题。

    例子:

    ' or '1=1】会被转义为【\' or \'1=1】
    

4.4、MyBatis解决SQL注入问题

MyBatis编写SQL语句的参数的2种方式:

  • ${value}:表示拼接字符串。会引起SQL注入问题。
  • #{value}:在预处理时,用占位符?来替代参数部分。可以解决SQL注入问题。

4.5、模糊查询举例

Mapper

/** 
* 模糊查询用户 
* @param str 用户名的一部分 
* @return 用户 
*/
List<User> getUserLikeStr(String str);

Mapper.xml

<select id="getUserLikeStr" parameterType="String" resultType="indi.jaywee.pojo.User">
    select * from mybatis.user
    where name like concat('%',#{str},'%');-- 防止SQL注入
</select>

JUnit

分别用拼接字符串常规填写的参数,调用接口方法,查看结果。

@Test
public void getUserLike() {
    // 获取SqlSession实例
    SqlSession sqlSession = MyBatisUtils.getSqlSession();

    // 获取Mapper
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 执行方法:尝试SQL注入
    List<User> users = mapper.getUserLikeStr("' or '1=1"); // SQL注入无法
    System.out.println("users");
    for (User user : users) {
        System.out.println(user);
    }

    System.out.println("-------------------------");
    
    // 执行方法:正常填写参数
    List<User> users1 = mapper.getUserLikeStr("d"); // SQL注入无法
    System.out.println("users1");
    for (User user1 : users1) {
        System.out.println(user1);
    }

    // 关闭连接
    sqlSession.close();
}

运行结果

可以看出:尝试SQL注入失败,一个用户都没查出来,有效防止了SQL注入。

 
标签: MyBatis
 
 
posted @ 2022-02-24 22:50  扬帆起航$  阅读(39)  评论(0)    收藏  举报