mybatis基于注解开发遇到问题汇总

来源:互联网 发布:邮箱域名大全 编辑:程序博客网 时间:2024/06/03 19:21

这里写代码片使用Mybatis开发持久层,庞大的xml配置文件提供了强大的功能,但是sql语句需要在xml文件中进行配置,并且必须遵循一定的规则。
现在可以使用注解开发来代替xml配置文件。具体的流程就不再赘述,可以查看《Java持久化之myBatis3》,此书大体介绍了注解开发,本文就实际开发中遇到的问题进行表述。

一. 参数绑定问题

1.#{}和${}使用出错

@Select("select ad.*,ac.name as name,ac.acsid from acs_door ad          left join acs_server ac on ad.serverid = ac.id where #{codingTerm}")List<AcsDoorBean> getList(@Param("codingTerm")String codingTerm);

codingTerm 是一个和权限有关的字符串,”coding like ‘%33%’”,
当使用#{}进行占位符操作时,junit单元测试控制台打印

==>Preparing: select ad.*,ac.name as name,ac.acsid from acs_door ad left join acs_server ac on ad.serverid = ac.id where ? ==> Parameters: ad.coding like '%33%'(String)<== Total: 0

不会抛异常,sql语句没问题,参数绑定也没问题,但是无法从数据库或得正确的数据。
所以考虑到#{}是提供占位符的操作而${}可以用来进行sql拼接,而codingTerm不是表中的字段,和实体类无法形成关系映射,所以不能使用占位符,进行替换后控制台打印如下,并且可以正常查出需要的数据。#{}就相当于sql语句的“?”进行占位操作。

==>  Preparing: select ad.*,ac.name as name,ac.acsid from acs_door ad left join acs_server ac on ad.serverid = ac.id where ad.coding like '%33%'  ==> Parameters: <==    Columns: id, serverid, deviceid, doorid, doorname, name, comment, doorstate, doorcontrolstate, coding, emapLeft, emapTop, emapId, name, acsid<==        Row: 1, 1, 33, null, null, null, null, null, null, 33, null, null, null, null, null <==       Row: 2, 2, 33, null, null, null, null, null, null, 33, null, null, null, <==      Total: 3

**当使用${}进行拼接式codingTerm参数钱必须加@Param(“codingTerm”)注解,否则会报错

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'codingTerm' in 'class java.lang.String'

二.输出参数问题

@Select("select id from acs_door where doorname=?")int isNameExistForAdd(@Param("doorname")String doorname);

当输出的参数id类型为int,返回值类型也是int,代码没问题,junit运行不报错,但得不到自己想要的结果,因为id是表中字段但没有映射的类的去封装,所以如果要返回值进行判断的话需改成

@Select("select count(id) from acs_door where doorname=?")int isNameExistForAdd(@Param("doorname")String doorname);

这样就能返回你所需要的int类型的值进行下一步的判断。
还有一个原因就是当你查询的对象id为null时,int也没办法作为返回值类型。

三.@SelectProvider注解的使用

@SelectProvider(type=AcsSqlProvider.class,method = "getAlarmListSql")    List<AcsAlarmBean> getAlarmList(AcsAlarmSearchBean alarmBean,String codingTerm, String sqlTermDeviceidDoorAlarm);

ACSSQLProvider类中提供sql语句,可以通过继承SqlBuilder类拼接规范sql,但是亲自测试不继承也能获取参数以及返回sql语句

public String getAlarmListSql(Map<String, Object> map)    {        AcsAlarmSearchBean searchBean = (AcsAlarmSearchBean) map.get("searchBean");        StringBuilder sql = new StringBuilder()        .append("select aa.*, ad.doorname as doorname from acs_alarm aa")        .append(" left join acs_door ad on ad.deviceid=aa.deviceid")        .append(" where ${codingTerm}")        .append(" and aa.deviceid in ${sqlTermDeviceidDoorAlarm}");        if ((searchBean.getDeviceid() != null) && (!searchBean.getDeviceid().equals("")))        {            sql.append(" and aa.deviceid=#{searchBean.deviceid}");        }        if (searchBean.getAlarmtype() != null)        {            sql.append(" and aa.alarmtype=#{alarmtype}");        }        if (searchBean.getAlarmstate() != null)        {            sql.append(" and aa.alarmstate=#{alarmstate}");        }        if ((searchBean.getAlarmTimeBegin() != null) && (searchBean.getAlarmTimeEnd() != null))        {            sql.append(" and alarmtime>=#{alarmTimeBegin} and alarmtime<DATE_ADD(#{alarmTimeEnd},INTERVAL 1 DAY)");        }        sql.append(" order by alarmtime desc ");        return sql.toString();    }

当出现两个append使{};如下

public String getAlarmListSql(Map<String, Object> map)    {        AcsAlarmSearchBean searchBean = (AcsAlarmSearchBean) map.get("searchBean");        String codingTerm = (String) map.get("codingTerm");        String sqlTermDeviceidDoorAlarm = (String) map.get("sqlTermDeviceidDoorAlarm");        StringBuilder sql = new StringBuilder()        .append("select aa.*, ad.doorname as doorname from acs_alarm aa")        .append(" left join acs_door ad on ad.deviceid=aa.deviceid")        .append(" where ").append(codingTerm)        .append(" and aa.deviceid in ").append(sqlTermDeviceidDoorAlarm);

还有一个问题,当通过#{alarmtype}来获取searchBean的alarmtype属性时会报绑定错误org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'alarmtype' not found. Available parameters are [sqlTermDeviceidDoorAlarm, param1, param2, codingTerm, param3, searchBean]
,必须用#{searchBean.alarmtype}来获取参数,参数绑定时无法识别#{alarmtype}的来源,必须指定。

原创粉丝点击