解决MyBatis中常见的错误

传递多个参数时出现的错误

dao层中的方法只传递一个参数,但需要传递多个参数时出现什么问题呢?

dao接口内容:

public interface RoleDao {
    //根据role_name和role_code查询用户
    public Role selectByNameAndCode(String name,String code);
}

对应接口的映射文件:

<select id="selectByNameAndCode" resultType="com.hrc.entity.Role">
   select * from t_role where role_name = #{name} and role_code=#{code}
 </select>

测试代码:

public class RoleTest {
    @Test
    public void queryTest() throws Exception{
        //读取 MyBatis配置文件资源
        //import org.apache.ibatis.io.Resources; 注意这里导入的包必须是ibatis下的
        Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
        //创建SqlSessionFactory工厂(根据读取mybatis配置文件进行创建)
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
        //开启SqlSession会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //通过映射关系,获取映射文件中对应的接口
        RoleDao roleDao = sqlSession.getMapper(RoleDao.class);
        //通过接口调用相关查询方法(注意一点:数据库中式存在这名角色的信息
        Role role = roleDao.selectByNameAndCode("老师", "teacher");
        //输出结果
        System.out.println("role = " + role);
    }
}

结果展示:

原因是:MyBatis中如何传递多个参数时默认第一个参数param1或arg0后面参数依次类推。

解决方法:

使用注解@Param("起别名"):通过给参数起别名的方式

例如:

效果展示:

实现模糊查询

 模糊查询的sql语句为:

select * from 表名  where 列名 like ''注意:
%表示匹配0个或多个字符
_:表示匹配一个字符

实现模糊查询拥有两种方法解决:

使用MySQL中函数concat()

语法:

concat(字符串a,字符串b,......,字符串n)

举个例子:

dao接口中的方法:

public interface RoleDao {
    //根据role_name模糊查询用户
    public List<Role> likeByName(String name);
}

对应其映射文件内容:

<select id="likeByName" resultType="com.hrc.entity.Role">
        select * from t_role where role_name like concat('%',#{name},'%')
</select>

效果展示:

 通过模糊查询,找到姓名存在管理员的人有三个

使用${}实现字符串拼接

语法:

${'\'%'++'%\''}

举个例子:

dao对应的映射文件内容:

效果展示:

这里出现的${}与#{}的区别

${}:一般是用于字符串拼接的,而字符串拼接会出现一个问题(SQL注入)

#{}:使用占位符的方式,mybatis通过PrepareStatement完成占位符赋值,可以有效的防止sql注入安全问题。

解决MyBatis映射文件中出现的特殊字符

由于MyBatis存在一些特殊含义的字符比如:>,<,',&

要如何解决这些特殊字符呢?

方法一:使用这些字符的转义字符

举个例子:

dao接口内容:

public interface StudentDao {
    //查询年龄在min与max之间的学生
    public List<Student> queryByAge(@Param("min") Integer min ,@Param("max") Integer max);
}

对应其映射文件内容:

效果展示:

方法二:使用<![CDATA[sql]]>实现

举个例子:

接口对应其映射文件内容:

<select id="queryByAge" resultType="com.hrc.entity.Student">
        <![CDATA[
        select * from t_student where age >= #{min} and age <=#{max}
        ]]]>
</select>

效果展示:

结果与之前的一样。

列名和属性名不一致

之前说过,数据库中列名要和属性名一致否则会出现数据库列内容映射不到实体类的属性值

这里我们可以使用两种方法解决这个问题

这里我将实体类Role中部分属性与数据库中列名不一致:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Role {
    //角色id与数据库中列名不一致
    private Integer rid;
    //角色的姓名与数据库中列名不一致
    private String name;
    //角色的编码与数据库中列名不一致
    private String code;
    //角色的描述与数据库中列名一致
    private String description;
}

方法一:给查询出来的数据库列名起别名

举个例子:

接口对应的映射器内容:

效果展示:

方法二:使用resultMap进行映射

举个例子:

效果展示:

结果与第二种方法的一致。

添加时获取递增主键的值

情景:数据库中主键一般自增形式,所以在添加的时候不需要为其提供主键值

所以当我们添加数据时,如何获取其对应的主键值呢?

方法:

使用属性useGeneratedKeys以及keyProperty

举个例子:

测试代码:

public class RoleTest {
    @Test
    public void queryTest() throws Exception{
        //读取 MyBatis配置文件资源
        //import org.apache.ibatis.io.Resources; 注意这里导入的包必须是ibatis下的
        Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
        //创建SqlSessionFactory工厂(根据读取mybatis配置文件进行创建)
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
        //开启SqlSession会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //通过映射关系,获取映射文件中对应的接口
        RoleDao roleDao = sqlSession.getMapper(RoleDao.class);
        //通过接口调用相关查询方法(注意一点:数据库中式存在这名角色的信息)
        Role role = new Role(null,"普通用户","user","一个普通的用户");
        System.out.println("添加前的role: " + role);
        roleDao.insertRole(role);
        sqlSession.commit();
        System.out.println("添加后的role: " + role);
    }
}

效果展示:

控制台的内容:

数据库的内容:

 

posted @ 2024-01-27 16:55  和哗  阅读(88)  评论(0编辑  收藏  举报