ibatis 测试时出现错误提示: “could not find sql statement to include with refid xxx” , 出现这种错误一般是下面两种情况引起:
- refid引用的sqlid不正确, 自己好好检查下。
- refid正确,但还是报错, 可能原因是: sql refid定义的位置必须在引用的语句之前,否则会出错。
DONE!
ibatis 测试时出现错误提示: “could not find sql statement to include with refid xxx” , 出现这种错误一般是下面两种情况引起:
DONE!
使用mybatis,mybatis-config配置文件已使用下面两行配置
<settings> <setting name="aggressiveLazyLoading" value="false" /> <setting name="lazyLoadingEnabled" value="true" /> </settings> 但发现还是懒加载无效,其实可能在你的代码里有tostring,equal等默认方法触发了懒加载调用,可以通过添加一个配置项解决问题,使用下面的配置 <settings> <setting name="aggressiveLazyLoading" value="false" /> <setting name="lazyLoadingEnabled" value="true" /> <setting name="lazyLoadTriggerMethods" value=""/> </settings> 说明: lazyLoadTriggerMethods : Specifies which Object's methods trigger a lazy load, 指定触发懒加载的方法名,用逗号分隔, 默认值:equals,clone,hashCode,toString
mybatis写sql语句时会看到#{}, ${}的写法,有什么区别呢?
1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。
2. $将传入的数据直接显示生成在sql中。如:select * from ${table};
3. #方式能够很大程度防止sql注入。
4.$方式无法防止Sql注入。
5.$方式一般用于传入数据库对象,例如传入表名,order by、like 语句只能用${}了,用#{}会多个’ ‘导致sql语句失效
6.一般能用#的就别用$.
mybatis下limit如果想做分页,对limit做参数计算时:
错误的写法:
<select id=”queryMyApplicationRecord” parameterType=”MyApplicationRequest” resultMap=”myApplicationMap”>
SELECT
a.*,
FROM
tb_user a
WHERE 1=1
<if test=”ids != null and ids.size()!=0″>
AND a.id IN
<foreach collection=”ids” item=”id” index=”index”
open=”(” close=”)” separator=”,”>
#{id}
</foreach>
</if>
<if test=”statusList != null and statusList.size()!=0″>
AND a.status IN
<foreach collection=”statusList” item=”status” index=”index”
open=”(” close=”)” separator=”,”>
#{status}
</foreach>
</if>
ORDER BY a.create_time desc
LIMIT (#{pageNo}-1)*#{pageSize},#{pageSize}; // 错误
</select>
在MyBatis中LIMIT之后的语句不允许的变量不允许进行算数运算,会报错。
正确的写法一:
<select id=”queryMyApplicationRecord” parameterType=”MyApplicationRequest” resultMap=”myApplicationMap”>
SELECT
a.*,
FROM
tb_user a
WHERE 1=1
<if test=”ids != null and ids.size()!=0″>
AND a.id IN
<foreach collection=”ids” item=”id” index=”index”
open=”(” close=”)” separator=”,”>
#{id}
</foreach>
</if>
<if test=”statusList != null and statusList.size()!=0″>
AND a.status IN
<foreach collection=”statusList” item=”status” index=”index”
open=”(” close=”)” separator=”,”>
#{status}
</foreach>
</if>
ORDER BY a.create_time desc
LIMIT ${(pageNo-1)*pageSize},${pageSize}; (正确)
</select>
正确的写法二:(推荐)
<select id=”queryMyApplicationRecord” parameterType=”MyApplicationRequest” resultMap=”myApplicationMap”>
SELECT
a.*,
FROM
tb_user a
WHERE 1=1
<if test=”ids != null and ids.size()!=0″>
AND a.id IN
<foreach collection=”ids” item=”id” index=”index”
open=”(” close=”)” separator=”,”>
#{id}
</foreach>
</if>
<if test=”statusList != null and statusList.size()!=0″>
AND a.status IN
<foreach collection=”statusList” item=”status” index=”index”
open=”(” close=”)” separator=”,”>
#{status}
</foreach>
</if>
ORDER BY a.create_time desc
LIMIT #{offSet},#{limit}; (推荐,代码层可控)
</select>
分析:方法二的写法,需要再请求参数中额外设置两个get函数,如下:
@Data
public class QueryParameterVO {
private List<String> ids;
private List<Integer> statusList;
// 前端传入的页码
private int pageNo; // 从1开始
// 每页的条数
private int pageSize;
// 数据库的偏移
private int offSet;
// 数据库的大小限制
private int limit;
// 这里重写offSet和limit的get方法
public int getOffSet() {
return (pageNo-1)*pageSize;
}
public int getLimit() {
return pageSize;
}
}
网上总结的4个方法,挺好的,分享下: https://blog.csdn.net/lmy86263/article/details/53150091
首先先定义一个测试实体类,如下:
public class User implements Serializable {
private Integer userId;
private String userName;
……
}
1. 通过XML映射文件中的resultMap
这种方式是最常见的,类似如下:
<mapper namespace=”data.UserMapper”>
<resultMap type=”data.User” id=”userResultMap”>
<!– 用id属性来映射主键字段 –>
<id property=”id” column=”user_id”/>
<!– 用result属性来映射非主键字段 –>
<result property=”userName” column=”user_name”/>
</resultMap>
</mapper>
通过里面的id标签和result标签来建立映射关系,由property和column分别指定实体类属性和数据表的列名。
2. 通过注解@Results和@Result
这两个注解是与XML文件中的标签相对应的:
@Results对应resultMap
@Result对应result
这两个注解是应用在方法的级别上的,也就是在mapper方法上,如下:
@Select(“select * from t_user where user_name = #{userName}”)
@Results(
@Result(property = “userId”, column = “user_id”),
@Result(property = “userName”, column = “user_name”)
)
User getUserByName(@Param(“userName”) String userName);
缺点:
由于注解是针对方法的,对于Mapper中的每个操作数据库的方法都必须有相同的注解完成映射关系的建立,导致很多的配置是重复的;
如果要避免配置重复的问题,可以采用在XML配置文件中配置这个resultMap,然后再@Result中通过id属性引用这个resultMap,
但是这样感觉很麻烦(由于使用了两种配置方式),不如直接使用基于XML的resultMap配置方式;
3. 通过属性配置完成映射
使用者最陌生的是通过配置属性来完成映射,Mybatis给我们提供了一种映射方式,如果属性的命名是遵从驼峰命名法的,数据列名遵从下划线命名,
那么可以使用这种方式,类似如下:
userName对应user_name;
userId对应user_id;
配置代码如下:
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
Configuration configuration = new Configuration();
configuration.setMapUnderscoreToCamelCase(true);
sqlSessionFactoryBean.setConfiguration(configuration);
4. 通过使用在SQL语句中定义别名完成映射
这种方式最直接,直接在SQL语句中建立别名来完成映射,如下:
@Select(“select user_name as userName, user_id as userId from t_user where user_name = #{userName}”)
User getUserByName(@Param(“userName”) String userName);