问题一:bind标签使用的问题
<select id="findBooks" parameterType="Book" resultType="Book" useCache="false"> <!-- if _parameter.getName() is null,NullPointerException will be throw! --> <!-- <bind name="nameParam" value="'%'+_parameter.getName()+'%'"/> <bind name="authorParam" value="'%'+_parameter.getAuthor()+'%'"/> --> select * from t_book <where> <if test="name != null"> name like concat(concat('%',#{name}),'%') </if> <if test="author != null"> and author like concat(concat('%',#{author}),'%') </if> <if test="category != null and category.id != null"> and category = #{category.id} </if> </where> </select>
由于要进行模糊查询,所以要对传入过来的值前后添加%
当使用bind进行绑定时,传入的值如果是NULL,就会抛出空指针异常,而且if标签下又没有bind标签,所以遇到传入的值可以为空的情况下,bind则不能使用。
解决办法:
1,使用concat方法,但是不同的数据库使用方式不一样.
Oracle: concat(concat('%',#{name}),'%')
Mysql: concat('%',#{name},'%')
2,通过java代码中构建好传入到配置文件中
问题二:向数据库中插入数据时如果由一个字段没有设置就会抛出异常(UncategorizedSQLException: Error setting null for parameter #4 with JdbcType OTHER . Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property.)
例如:<insert id="saveBook" parameterType="Book"> <selectKey resultType="string" order="BEFORE" keyProperty="id"> SELECT SYS_GUID() FROM DUAL </selectKey> insert into t_book(id,name,publishDate,author,price,category,quantity) values(#{id},#{name},#{publishDate},#{author},#{price}, #{category,jdbcType=VARCHAR,typeHandler=CategoryTypeHandler},#{quantity}) </insert>如果传入的 book 类型的 name 属性或其他属性没有设置值就抛出上面的异常。
解决办法:
在mybatis-config.xml配置文件中设置jdbcTypeForNull的值为NULL,默认是OTHER
<settings>
<setting name="jdbcTypeForNull" value="NULL"/>
</settings>
问题三:向数据库中插入一个对象时,其关联的对象属性不能直接通过OGNL来进行设置,需要写一个类型转换器.
例如:
Book.java(外键一个图书类型)
public class Book implements Serializable {
private static final long serialVersionUID = 8634505584095346474L;
private String id;
private String name;
private Date publishDate;
private String author;
private Float price;
private Category category;
private Long quantity;
getter ,setter方法省略…
}
Category.java
public class Category implements Serializable {
private static final long serialVersionUID = 8964146416205979692L;
private String id;
private String name;
private String spell;
private String comments;
public Category() {
super();
}
public Category(String id) {
super();
this.id = id;
}
getter ,setter方法省略…
}
mapper配置文件(BookMapper.xml)中的insert语句(这种配置会报错)
<insert id="saveBook" parameterType="Book">
<selectKey resultType="string" order="BEFORE" keyProperty="id">
SELECT SYS_GUID() FROM DUAL
</selectKey>
insert into t_book(id, ,name,publishDate,author,price,category,quantity)
values(#{id},#{name},#{publishDate},#{author},#{price},#{category.id},
# {quantity})
</insert>
解决办法(感觉有其它更好的解决办法):
配置如下:
<insert id="saveBook" parameterType="Book"> <selectKey resultType="string" order="BEFORE" keyProperty="id"> SELECT SYS_GUID() FROM DUAL </selectKey> insert into t_book(id, ,name,publishDate,author,price,category,quantity) values(#{id},#{name},#{publishDate},#{author},#{price}, #{category,jdbcType=VARCHAR,typeHandler=CategoryTypeHandler},#{quantity}) </insert>
其中jdbcType和typeHandler需要指定; CategoryTypeHandler.java是自定义的类型处理器。
CategoryTypeHandler.java代码如下:
public class CategoryTypeHandler extends BaseTypeHandler<Category> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
Category parameter, JdbcType jdbcType) throws SQLException {
if (jdbcType == null) {
ps.setString(i, parameter.getId());
} else {
ps.setObject(i, parameter.getId(), jdbcType.TYPE_CODE); // see r3589
}
}
@Override
public Category getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return null;
}
@Override
public Category getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
return null;
}
@Override
public Category getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return null;
}
}
然后配置在mybatis-config里配置处理器和别名
<typeAliases> <typeAlias type="com.bookshop.book.typehandler.CategoryTypeHandler" alias="CategoryTypeHandler"/> </typeAliases> <typeHandlers> <typeHandler handler="com.bookshop.book.typehandler.CategoryTypeHandler" /> </typeHandlers>
关于问题三特别说明下:上面提到通过OGNL进行设置会出错,在我后面的测试中,通过OGNL又成功了,
所以问题三可能不是一个问题。