Mybatis学习(四):Mybatis关系映射文件CRUD与参数处理

写在前边: 今天给大家讲解Mybatis中的关系映射文件CRUD与参数处理
公众号:小白编码

Mybatis关系映射文件

mapper常用属性:

  • namespace:名称空间;指定为接口的全类名

  • id:唯一标识

  • resultType:返回值类型

  • #{id}:从传递过来的参数中取出id值

  • parameterType参数类型

关系映射文件CRUD

mapper接口:

public interface EmployeeMapper {

    List<Employee> getAllEmp();

    void addEmp(Employee emp);

    int updateEmp(Employee emp);

    boolean deleteEmpById(Integer id);

}

sql关系映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--配置查询所有(是Dao里面的方法)
 namespace:名称空间;指定为接口的全类名
-->
<mapper namespace="cn.codewhite.dao.EmployeeMapper">

    <!--  List<Employee> getAllEmp();
             id:唯一标识
           resultType:返回值类型
    -->
    <select id="getAllEmp" resultType="emp" databaseId="mysql">
        select * from tbl_employee
    </select>

    <!--    void addEmp(Employee emp);
     parameterType参数类型
      #{id}:从传递过来的参数中取出id值
    -->
    <insert id="addEmp" parameterType="cn.codewhite.pojo.Employee">
        insert into tbl_employee(last_name,email,gender)
        values (#{lastName},#{email},#{gender})
    </insert>

    <!--    int updateEmp(Employee emp);-->
    <update id="updateEmp" parameterType="cn.codewhite.pojo.Employee">
        update tbl_employee
        set last_name = #{lastName},email = #{email},gender = #{gender}
        where id = #{id}
    </update>

    <!--    boolean deleteEmpById(Integer id);-->
    <delete id="deleteEmpById" parameterType="cn.codewhite.pojo.Employee">
        delete from tbl_employee where id = #{id}
    </delete>

CRUD前:

CRUD后:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ybWQFxnx-1590116276181)()]

CRUD测试代码:

 @Test
    public void testCRUD() {

        SqlSession sqlSession = null;
        try {
            SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
            //1、获取到的SqlSession不会自动提交数据
            sqlSession = sqlSessionFactory.openSession();
            EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
            //查询
            List<Employee> allEmp = mapper.getAllEmp();
            allEmp.forEach(System.out::println);

            //插入1个员工
            mapper.addEmp(new Employee(null, "新插入员工", "codewhite@qq.com", 1, null));
            //修改4号员工
            System.out.println(mapper.updateEmp(new Employee(4, "4号员工", "codewhite@qq.com", 1, null)));
            //删除1号员工
            System.out.println(mapper.deleteEmpById(1));
            //2、提交数据
            sqlSession.commit();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
                if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

注意问题: 增删改需要提交事务!!!否则无法生效

MySQL获取主键

mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGenreatedKeys();
useGeneratedKeys="true";使用自增主键获取主键值策略
keyProperty;指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性

  <insert id="addEmp" parameterType="cn.codewhite.pojo.Employee"
           useGeneratedKeys="true" keyProperty="id">
       insert into tbl_employee(last_name,email,gender)
       values (#{lastName},#{email},#{gender})
   </insert>

测试代码:此时就能够获取刚刚add的员工的id了

//插入1个员工
            Employee employee = new Employee(null, "新插入员工3", "codewhite@qq.com", 0, null);
            mapper.addEmp(employee);
            System.out.println(employee.getId());

打印结果:14

Mybatis参数处理

何为参数: 参数就是接口方法里定义的形参,然后需要在xml关系映射文件中使用#{参数名}获取参数。

如:Mapper接口方法:

Employee getEmpById(Integer id)

映射文件: 其中#{id}就是获取参数

<select id="getEmpById" resultType="cn.codewhite.pojo.Employee">
		select * from tbl_employee where id = #{id}
</select>
单个参数:

mybatis不会做特殊处理,
因为只有一个参数
#{参数名/任意名}:取出参数值。

Mapper映射文件:#{id}可以写成#{任意名}

原因:在Mapper接口只定义了一个参数Employee getEmpById(Integer id);

关系映射文件: 此时的#{id}可以写成任何名,如:#{idxxxx}都能够识别参数id

<select id="getEmpById" resultType="cn.codewhite.pojo.Employee">
		select * from tbl_employee where id = #{id}
</select>

测试:

getEmpById(1)结果:
Employee [id=1, lastName=Tom, email=jerry@atguigu.com, gender=0]
多个参数:

mybatis会做特殊处理。
多个参数会被封装成 一个map
key:param1…paramN,或者参数的索引也可以
value:传入的参数值
#{}就是从map中获取指定的key的值;

接口方法:Employee getEmpByIdAndLastName(Integer id,String lastName);
若直接使用#{id},#{lastName}取值,那么会直接报异常:
org.apache.ibatis.binding.BindingException: 
Parameter 'id' not found. 
Available parameters are [1, 0, param1, param2]
    
解决方法:使用命名参数,使用多个参数处理。

如何使用多个参数处理:

sql关系映射文件配置:

<select id="getEmpByIdAndLastName" resultType="cn.codewhite.pojo.Employee">
			select * from tbl_employee where id = #{param1} and last_name = #{param2}
</select>
	
或者:
<select id="getEmpByIdAndLastName" resultType="cn.codewhite.pojo.Employee">
				select * from tbl_employee where id = #{arg0} and last_name = #{arg1}
</select>
使用命名参数:

明确指定封装参数时map的key;使用注解:@Param("id")
多个参数会被封装成 一个map,
key:使用@Param注解指定的值
value:参数值
#{指定的key}取出对应的参数值

如何使用: 在方法里添加注解@Param("xxx") 注解方式:

EmployeeMapper接口方法:

Employee getEmpByIdAndLastName(@Param("id") Integer id, @Param("lastName") String lastName);

sql关系映射文件:此时就可以直接使用#{注解中定义的参数名}

 <select id="getEmpByIdAndLastName" resultType="cn.codewhite.pojo.Employee">
         select * from tbl_employee where id = #{id} and last_name = #{lastName}
 </select>

Map方式解决:

EmployeeMapper接口方法:

Employee getEmpByMap(Map<String, Object> map);

sql关系映射文件配置:

	<select id="getEmpByMap" resultType="cn.codewhite.pojo.Employee">
				select * from tbl_employee where id = #{id} and last_name = #{lastName}
	</select>

测试使用:通过map自定义key-value值来配置参数。

@Test
    public void testMap(){

        SqlSession sqlSession = null;
        try {
            SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
            
            sqlSession = sqlSessionFactory.openSession();
            EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
            //重点:使用map定制,向map中放入指定的属性与属性值
            Map<String, Object> map = new HashMap<>();
            map.put("id",5);
            map.put("lastName","xiaobai");
            System.out.println(mapper.getEmpByMap(map));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

测试结果:Employee(id=5, lastName=xiaobai, email=xiaobai@qq.com, gender=1, dept=null)
参数处理推荐使用方法:

推荐的用法:POJO,MAP,TO。

POJO使用如下:

EmployeeMapper接口方法定义:

	Employee getEmpByIdAndLastName(Employee employee);

XML:

<select id="getEmpByIdAndLastName" resultType="cn.codewhite.pojo.Employee">
         select * from tbl_employee where id = #{id} and last_name = #{lastName}
</select>

测试方法:通过javabean的属性来查询

  @Test
  public void getEmpByIdAndLastName() throws IOException {

      SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();

      SqlSession sqlSession = sqlSessionFactory.openSession();
      EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
      Employee tom = mapper.getEmpByIdAndLastName(new Employee(1, "Tom", null, null));
      System.out.println(tom);
  }

MAP使用: 就是5.2.4里的map方法。

TO使用:
如果多个参数不是业务模型中的数据,但是经常要使用,推荐来编写一个TO(Transfer Object)数据传输对象

Page{
	int index;
	int size;
}
参数处理总结:
public Employee getEmp(@Param("id")Integer id,String lastName);

那么xml中取值:id==>#{id/param1} lastName==>#{param2}

public Employee getEmp(Integer id,@Param("e")Employee emp);

那么xml中取值:id==>#{param1} lastName===>#{param2.lastName/e.lastName}

注意: 如果是Collection(List、Set)类型或者是数组,
也会特殊处理。也是把传入的list或者数组封装在map中。
key:Collection(collection),如果是List还可以使用这个key(list)
数组(array)

public Employee getEmpById(List<Integer> ids);

#{}与${}的区别:

#{}:可以获取map中的值或者pojo对象属性的值;
${}:可以获取map中的值或者pojo对象属性的值;

xml映射文件:

select * from tbl_employee where id=${id} and last_name=#{lastName}
执行结果:Preparing: select * from tbl_employee where id=2 and last_name=?

以上测试代码发现:

#{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入
${}:取出的值直接拼装在sql语句中;会有安全问题

使用:原生jdbc不支持占位符的地方我们就可以使用${}进行取值
比如分表、排序…;按照年份分表拆分

select * from ${year}_salary where xxx;
select * from tbl_employee order by ${f_name} ${order}

#{}:更丰富的用法:
规定参数的一些规则:
javaTypejdbcTypemode(存储过程)numericScale、
resultMaptypeHandlerjdbcTypeNameexpression(未来准备支持的功能);

jdbcType通常需要在某种特定的条件下被设置:
在我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理。比如Oracle(报错);
JdbcType OTHER:无效的类型;因为mybatis对所有的null都映射的是原生Jdbc的OTHER类型,oracle不能正确处理;
由于全局配置中:jdbcTypeForNull=OTHER;oracle不支持;两种办法
1、#{email,jdbcType=OTHER};
2、jdbcTypeForNull=NULL
<setting name="jdbcTypeForNull" value="NULL"/>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值