Mybatis----自增主键、参数处理、取值、空值处理

在上一篇增删改查的基础上继续:

获取自增主键需要数据库支持自增主键
MySQL支持自增主键键值的获取,mybatis也是利用jdbc中statement.getGeneratedKey(),

  • useGeneratedKeys=“true”:使用自增主键获取主键值策略
  • keyProperty=“id”:指定对应的主键属性:也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性
<!--public int addEmp(Employee e);-->
<!--  parameterType:参数类型,可以省略  -->
    <insert id="addEmp" parameterType="bean.Employee"
            useGeneratedKeys="true" keyProperty="id">
        insert into tbl_employee(last_name,email,gender)
        value(#{lastName},#{email},#{gender})
    </insert>
一、参数处理:

单个参数:
mybatis不做任何处理,因为只有一个参数,相当于一个占位符。
直接#{参数名}:取出参数的值


多个参数:
会做特殊处理,多个参数会被封装成一个map

  • key:param1…paramN,或者参数的索引
  • value:传入参数的值

请看下面的操作引发的异常

  1. mapper接口中:
    方法:public Employee getEmpByIdAndLastName(Integer id,String lastName);
  2. mapper.xml中直接拿传入的的参数名取值,但是mybatis不认识。
    取值:#{id},#{lastName}
  3. 异常主要信息:
    org.apache.ibatis.binding.BindingException:
    Parameter ‘id’ not found.
    Available parameters are [arg1, arg0, param1, param2]

也印证了上面的结论。


命名参数:
明确指定封装参数时map的key:@Param(“id”),@Param(“lastName”),多个参数会被封装成一个map。

  • key:使用@Param注解指定的值
  • value:参数值,#{指定的key}即可取出对应的参数值

POJO:
如果多个参数正好是业务逻辑的数据模型,可以直接传入pojo;#{属性名}:取出传入pojo的属性值


Map:
如果多个参数不是数据模型中的数据,没有对应的pojo,为了方便,可以传入map。

public Employee getByMap(Map<String,Object> map);
<!--public Employee getByMap(Map<String,Object> map);-->
    <select id="getByMap" resultType="emp">
        select * from tbl_employee where id = #{id} and last_name = #{lastName}
    </select>

测试

    public SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "config\\mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
    }
    
@Test
    public void test() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession openSession = sqlSessionFactory.openSession();
        try {
            EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
            
            Map<String,Object> map = new HashMap<>();
            map.put("id", 1);
            map.put("lastName", "jerry");
            Employee e = mapper.getByMap(map);
            System.out.println(e);
        }finally {
            openSession.close();
        }
    }

如果多个参数不是业务模型中的数据,但是经常要使用,推荐编写DTO(Transfer Object)数据传输对象 ,专门抽取一个对象用于传输。此处不做测试,原理类似POJO。


思考:

public Employee getEmp (@Param("id" )Integer id,String lastName) ;
取值:

  • id==>#{id/param1}
  • lastName==>#{param2}

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

  • id==>#{param1}
  • lastName===>#{param2.1astName/e.lastName}

特别注意,如果是Collection (List、Set)类型或者是数组,也会特殊处理。也是把传入的list或者数组封装在map中。

  • key:
    Collection(collection)
    List(list)
    数组(array)
  • 示例:查出 id 集合中所有对应的员工
    public Employee getEmpById(List<Integer> ids);
    取值,取出第一个id的值: #{ids[0]},#{param1[0]}都是错的,正确的写法是#{list[0]}

二、参数取值

id=${id} last_name=#{lastName}用这两种不同的方式取值,来对比$和#的区别:

select * from tbl_ employee where id=${id} and last_ name=#{lastName}
请看日志打印出来的SQL语句:
Preparing: select * from tbl_ employee where id=2 and last_ name=?


区别:

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

大多情况下,我们去参数的值都应该去使用#{};


好处:原生jdbc不支持占位符的地方我们就可以使用${ }进行取值:

  • 比如分表:
    按照年份分表拆分,2017_salary,2018_salary这种拼串就很方便
    select * from ${year}_ salary where xxx;
  • 比如用某个字段排序,升序还是降序
    select * from tbl_employee order by ${o_name} ${order};

#{}:更丰富的用法:
规定参数的一些规则:
javaType=#{xxx}、jdbcType. mode (存储过程)、numericScale、
resultMap、typeHandler、 jdbc TypeName、expression (未来准备支持的功能) ;

三、空值处理

jdbcType通常需要在某种特定的条件下被设置:
在我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理。比如Oracle (报错)
异常为:
JdbcType OTHER: 无效的类型:
原因:
因为mybatis对所有的null都映射的是原生JDBC的OTHER类型
解决办法:

  • 解决办法1:取值时指定类型 #{lastName,jdbcType=NULL}
  • 解决办法2:全局配置里面settings <setting name="jdbcTypeForNull" value="NULL"/>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值