怎么操作Blob类型的字段

长沙凡人 发布于 2012/07/11 18:03
阅读 3K+
收藏 1

如题,jfinal是否能支持呢?在例子工程里没看到。

而且也没看到Db的使用方法

加载中
2
长沙凡人

我在html页面上使用#{user.thumb}提示如下

Expecting a string, date or number here, Expression u.Body is instead a freemarker.ext.beans.ArrayModel
 at freemarker.core.Expression.getStringValue(Expression.java:126)
 at freemarker.core.Expression.getStringValue(Expression.java:93)
 at freemarker.core.DollarVariable.accept(DollarVariable.java:76)
 at freemarker.core.Environment.visit(Environment.java:210)
 at freemarker.core.MixedContent.accept(MixedContent.java:92)
 at freemarker.core.Environment.visit(Environment.java:210)
 at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:167)
 at freemarker.core.Environment.visit(Environment.java:417)
 at freemarker.core.IteratorBlock.accept(IteratorBlock.java:102)
 at freemarker.core.Environment.visit(Environment.java:210)
 at freemarker.core.MixedContent.accept(MixedContent.java:92)
 at freemarker.core.Environment.visit(Environment.java:210)
 at freemarker.core.Environment.process(Environment.java:190)
 at freemarker.template.Template.process(Template.java:237)
 at com.jfinal.render.FreeMarkerRender.render(FreeMarkerRender.java:124)

看起来貌似freemarker不支持blob的读取,这个不熟,还请知道的指教一下

1
opal
opal
#{user.parentid!}
0
JFinal
JFinal

JFinal是支持Blob类型的,不仅如此,还支持Clob以及NClob类型。Blob被JFinal自动提取为byte[]了,所以要使用byte[]变量来接收。获取该对象时与其它类型字段的方法是一样的:

byte[] thumb = user.get("thumb");
// 或者明确返回类型,如下:
byte[] thumb = user.getBytes("thumb");

 相关处理细节见com.jfinal.plugin.activerecord.ModelBuilder.java 中的handleBlob(...)方法:

  static byte[] handleBlob(Blob blob) throws SQLException {
    InputStream is = null;
    try {
      is = blob.getBinaryStream();
      byte[] data = new byte[(int)blob.length()];
      is.read(data);
      is.close();
      return data;
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    finally {
      try {is.close();} catch (IOException e) {throw new RuntimeException(e);}
    }
  }

    另外 Clob NClob 已经被转换为String类型,直接使用即可 :)

0
JFinal
JFinal

补充一下,如果你要在 Freemarker中显示Blob字段的值,可以将值转成 String再输出:

byte[] thumb = user.get("thumb");
user.set("thumb", new String(thumb));

0
长沙凡人
明白了,谢谢,不过既然可以转成String输出,为什么在Record里不直接将blob字段转成String进行处理,这样对外直接像其他普通字段一样使用Dao进行操作呢?
0
长沙凡人

补充一个发现的新问题,我字段定义为varchar,没有赋值(即为空),此时通过freemarker的#{user.parentid}获取时报错,说字段不存在,赋值后运行正常,是否jfinal在处理字段空值时还有问题?

freemarker.core.InvalidReferenceException: Expression u.ParentNoteID is undefined on line 11, column 31 in demo.html. at freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:124) at freemarker.core.Expression.getStringValue(Expression.java:118) at freemarker.core.Expression.getStringValue(Expression.java:93) at freemarker.core.DollarVariable.accept(DollarVariable.java:76) at freemarker.core.Environment.visit(Environment.java:210) at freemarker.core.MixedContent.accept(MixedContent.java:92) at freemarker.core.Environment.visit(Environment.java:210) at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:167) at freemarker.core.Environment.visit(Environment.java:417) at freemarker.core.IteratorBlock.accept(IteratorBlock.java:102) at freemarker.core.Environment.visit(Environment.java:210) at freemarker.core.MixedContent.accept(MixedContent.java:92) at freemarker.core.Environment.visit(Environment.java:210) at freemarker.core.Environment.process(Environment.java:190) at freemarker.template.Template.process(Template.java:237) at com.jfinal.render.FreeMarkerRender.render(FreeMarkerRender.java:124) at com.jfinal.core.ActionHandler.handle(ActionHandler.java:91) at com.jfinal.core.JFinalFilter.doFilter(JFinalFilter.java:65)

进一步测试发现如果没有使用上面你所说的set方法设置blob字段的值,则null字段可以正常操作,一旦set了就不行

我是这样的,首先从数据库取值,然后setattr,接着在html上用${u.Body}进行显示

controller:

  List<Notes> lu = Notes.dao.find("select * from T_SYS_NOTES");
  for (Notes r : lu) {
   r.set("Body",new String(r.getBytes("Body")));
  }
  setAttr("Notes",lu);

html:

<#list Notes as u>
 <li>Body=${u.Body} - ParentNoteID=${u.ParentNoteID}</li>
</#list>

 红色背景部分导致html报错

JFinal
JFinal
回复 @thclucky : 你调试一下,可能Notes.dao.find(...)这句并没有返回Body这个字段,或者这个字段的值为 null。Freemarker不支持null值输出,更不支持不存在的变量输出 :)
长沙凡人
我用的是MySQL,大小写敏感,但肯定不是这个原因造成的,因为如果我对Body赋了值,使其不为空,则程序执行没有问题,一旦为空,这会执行红色部分的代码,然后就html报找不到字段的错了
JFinal
JFinal
你用的是什么数据库?如果是 oracle注意一下属性大小写问题,从model中读取数据时对大小写是敏感的,而oracle通常把属性自动全部转换成大写,如果不是这个问题,请贴freemarker错误提示
0
JFinal
JFinal

引用来自“thclucky”的答案

明白了,谢谢,不过既然可以转成String输出,为什么在Record里不直接将blob字段转成String进行处理,这样对外直接像其他普通字段一样使用Dao进行操作呢?
因为Blob 类型有时存放的不是String数据,例如你可能存放的是图片数据 :)
0
龙影
龙影

可以这么解决:

定义一个StringKit中的blob转string方法:

public class StringKit{
public static final StringKit kit=new StringKit();
/**blob转stiring*/
public String fromBlob(Object con){
if(con==null){
return "";
}
if(con instanceof String ==false)
return new String((byte[])con);
else{
return (String) con;
}
}
}

request.setAttribute("StringKit", StringKit.kit);

然后在freemark里:

${StringKit.fromBlob((po.remark)!)}

就可解决

返回顶部
顶部