Mybatis系列总结2
友情提醒,阅读本文前,可以先阅读Mybatis系列总结1。
There is no getter for property named ‘ids’ in ‘class java.lang.String’
比较具体的报错信息为:
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'ids' in 'class java.lang.String'
@Options
insert后获取主键
首先,想要获取的注解,名字随意,可能不叫id
,但是必须要确保设置为auto_increment
。
代码层:
int num = dashboardCategoryMapper.insert(dashboardCategory);
<insert id="insert" parameterType="com.xy.cloudiview.common.model.DashboardCategory"
useGeneratedKeys="true" keyProperty="categoryId" keyColumn="category_id">
insert into category (category_name, user_id,
type, update_user_name, parent_id)
values (#{categoryName,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR},
#{type,jdbcType=INTEGER}, #{updateUserName,jdbcType=VARCHAR}, #{parentId,jdbcType=BIGINT})
</insert>
然后在代码层:dashboardCategory.getCategoryId()
获取主键,而不是num,num永远都是1,表示影响的记录数。
#{}
和${}
的区别
#{}
相当于对数据加上双引号,${}
相当于直接显示数据;#{}
能够很大程度上防止SQL注入,而${}
则不能;${}
方式一般应用于传入数据库对象,如表名;- 一般能用
#{}
的地方不要使用${}
; - 动态排序时,
order by column
,只能使用${}
;如果使用#{}
,拼接得到的SQL会加上引号,如order by 'dataset_id'
,执行会报错:
Mapper method attempted to return null from a method with a primitive return type (int).
报错查询语句如下:
int checkLastViewTime(Long widgetId);
<select id="checkLastViewTime" resultType="java.lang.Integer">
SELECT datediff(now(), last_view_time)
FROM widget
WHERE isactive = 1
AND widget_id = #{widgetId}
</select>
原因很容易定位到
一开始如下更改:
结果还是报同样的错误信息。
参考:解决方案,将Dao接口类里面的方法改成包装类型即可,ifnull完全没有效果:
@SelectKey
先看源码,mybatis-3.4.6:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SelectKey {
String[] statement();
// selectKey 语句结果应该被设置的目标属性。
String keyProperty();
String keyColumn() default "";
// true:首先选择主键,设置 keyProperty 然后执行插入语句;
// false:先执行插入语句,然后是 selectKey 元素-这和 Oracle 数据库相似,可以在插入语句中嵌入序列调用。
boolean before();
// 结果的类型。MyBatis 通常可以算出来,但是写上也没有问题。MyBatis 允许任何简单类型用作主键的类型,包括字符串。
Class<?> resultType();
// MyBatis 支持 STATEMENT ,PREPARED 和CALLABLE 语句的映射类型,分别代表 PreparedStatement 和CallableStatement 类型。
StatementType statementType() default StatementType.PREPARED;
}
StatementType枚举类:
public enum StatementType {
STATEMENT, PREPARED, CALLABLE
}
SelectKey在Mybatis中是为了解决Insert数据时不支持主键自动生成的问题,可以很随意的设置生成主键的方式。SelectKey需要注意order属性,像MySQL一类支持自动增长类型的数据库中,order需要设置为after才会取到正确的值。像Oracle这样取序列的情况,需要设置为before,否则会报错。
有用于mapper.xml 以及mapper接口中两种形式。
例子:
<insert id="insert" parameterType="map">
insert into table1 (name) values (#{name})
<selectKey resultType="java.lang.Integer" keyProperty="id">
CALL IDENTITY()
</selectKey>
</insert>
xml的传入参数是map,selectKey会将结果放到入参数map中。用POJO的情况一样,keyProperty对应的字段在POJO中必须有相应的setter方法,setter的参数类型还要一致,否则会报错。
@Insert("insert into table2 (name) values(#{name})")
@SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class)
int insertTable2(Name name);
MyBatis-PageHelper
官网:https://github.com/pagehelper/Mybatis-PageHelper
通用的分页插件,使用时 Mybatis 最低版本不能低于3.3。
原理:通过 AOP 在截获执行 SQL 时把相关的数据再执行一次。使用时,maven dependency需要添加的依赖包括:pagehelper、mybatis-paginator、jsqlparser。同时在spring配置文件添加:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath*:mappers/*Mapper.xml"></property>
<!-- 分页插件 -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageHelper">
<property name="properties">
<value>
<!-- 数据库方言 -->
dialect=mysql
</value>
</property>
</bean>
</array>
</property>
</bean>
Mybatis配置多个分页插件
<plugins>
<plugin interceptor="org.mybatis.pagination.PaginationInterceptor">
<property name="dbms" value="mysql"/>
<property name="sqlRegex" value=".*Paging.*"/>
</plugin>
<plugin interceptor="com.github.pagehelper.PageHelper">
<!--配置数据库方言 -->
<property name="dialect" value="mysql"/>
<!--<property name="offsetAsPageNum" value="false"/>-->
<!--<property name="rowBoundsWithCount" value="false"/>-->
<!--<property name="pageSizeZero" value="true"/>-->
<!--<property name="reasonable" value="false"/>-->
<!--<property name="supportMethodsArguments" value="false"/>-->
<!--<property name="returnPageInfo" value="none"/>-->
</plugin>
</plugins>
Mybatis IDEA 插件
作为应用最广泛的两个ORM框架之一,Mybatis有其成功之处,不过也有麻烦的时候,此时配上IDEA的mybatis插件,能够大大提升开发效率。
MyBatisCodeHelper
IDEA下代码自动生成插件,支持生成Mybatis的dao接口,mapper xml和建表SQL,支持直接从接口方法名直接生成SQL。关于插件的使用,这里有很详细的介绍,支持的特性包括但不限于:
- 根据数据库对象一键生成 Dao接口,Service,Xml,数据库建表SQL文件提供dao与xml的跳转;
- 根据dao中的方法名生成对应的mapper SQL并进行方法补全;
- Mybatis接口方法名重构支持;
安装:
idea常规的插件安装方式,会发现找不到该插件。倒是可以搜索到MyBatisCodeHelperPro,意思很明显,是升级版,需要付费或者破解之后才可以使用。看来并不是完全开源的。故而可以转向使用下面的插件,功能差不多都是类似的,足够日常开发;付费的高级功能如果要用到时可以尝试破解或者掏钱。
MyBatis plugin
很重的插件,最新版13.7M;
官网https://www.codesmagic.com/,有很多强大的功能,暂时还没有试用。
Free MyBatis plugin
MyBatisX
对应的框架是MyBatis-plus,有待试用。
参考
Mybatis的@Options注解
Mybatis 示例之 SelectKey
Mybatis中的@SelectKey注解
MyBatisCodeHelper
mybatis-how-to-get-the-auto-generated-key-of-an-insert-mysql