问题一: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又成功了,
所以问题三可能不是一个问题。