您的位置:首页 > 编程语言 > Java开发

关于在Hibernate、Struts2中使用Clob数据类型

2015-04-14 11:07 435 查看
关于在Hibernate、Struts2中使用Clob数据类型

情景假设:你需要存储一篇文档,假设文档的属性有四个,分别为:id(作为Hibernate主键)、title(标题)、content(内容)、publishTime(发布时间),当然,在不考虑复杂的情景下(比方说你想要记录文档的状态-发布或者草稿、版本号等等),这四个属性足够了。我们的焦点不是id、title或者publishTime,而是content。这里应该有以下的疑问:

·content应该使用什么样的数据库类型

·content应该使用什么样的Java类型

首先,先解决使用什么样的数据库类型。文档中存储的都是字符串(当然,附件这种二进制数据一般是存储在其他表格中的),那么假设t_document为文档表,其中的content列使用的肯定就是字符串数据类型了,再次假定使用的数据库是mysql,在mysql数据库中,varchar类型与char类型都是字符串。varchar类型长度是21000多,或许你以为这个数值很大了,足够满足大部分的文档内容要求了,但是在这里我告诉你,实际应用中往往是从一些office文档中直接拷贝一段文字然后放到我们的html编辑器,之后就提交到数据库的。一个包含了1000个字符左右的word文档,拷贝到html编辑器之后,其长度可能增长了一倍都不止。所以,2000多个字符的word文档,极可能拷贝到html编辑器后包含了20000个字符以上,这时候,如果你使用varchar作为数据库类型,那么在Java程序运行时,就要报MysqlSqlException了,因为存储的数据过长了,数据库不能进行处理(varchar数据类型是这样,而char数据类型则会进行剪裁,实际应用中,varchar类型用得居多,尤其是长字符串)。上述问题要怎么解决呢?在mysql里面,针对大文本,有三个数据类型(text、mediumtext、longtext),这三个大文本数据类型,能够存储几十万个字符,这足够满足我们的项目需求了。

其次,解决使用什么样的java类型。java的字符串,虽说不见得有长度限制,但是,针对数据库的大文本类型,hibernate却是提倡使用Clob(java.mysql.Clob)的,并且hibernate为Clob提供了实现ClobImpl(Clob只是一个接口,不能被直接使用)。这个实现给我们提供了一个ClobImpl(String str)的构造器,这意味着你可以使用你最熟悉的String来构造ClobImpl。此外,在将ClobImpl转换成为String的时候,也很方便,ClobImpl#getSubString(int pos, int len),参数pos是起始位置,从1开始,len是读取的串的长度。

Hibernate的大文本数据类型解决掉了,但是在Web层,传递的数据都是String,我们会有需求,将String在Web层转换成为Clob对象,并且在Service层回传对象给Web层时,将Clob转换成为字符串。在这里,Web层使用的MVC框架是Struts2,有两种解决方式,第一,在传递参数的时候,不使用领域模型,而是使用零散的参数,比如需要content,就在Action中声明String content域,而不是声明一个Document document域,在传递给Service层之前,把content通过手工代码转换成为一个Clob对象。另外一种方式就是,结合Struts2的Converter,这里推荐使用Struts2TypeConverter,在Action中声明Clob content域,让Strut2的转换功能帮助我们把String转换成为Clob,在提交给Service层处理。

附上手工转换Clob代码

package com.nytech.core.web.action.admin;

import java.util.Set;

import org.hibernate.lob.ClobImpl;

import com.nytech.core.entity.model.Document;
import com.nytech.core.web.action.base.BaseJsonAction;
import com.nytech.utils.model.CommonUtils;
import com.nytech.utils.model.JSONConstant;

/**
* @author daniel
*
*/
@SuppressWarnings("serial")
public class AddDocumentAction extends BaseJsonAction {

private String title;

private String content;

/**
* @return the title
*/
public String getTitle() {
return title;
}

/**
* @param title the title to set
*/
public void setTitle(String title) {
this.title = title;
}

/**
* @return the content
*/
public String getContent() {
return content;
}

/**
* @param content the content to set
*/
public void setContent(String content) {
this.content = content;
}

/* (non-Javadoc)
* @see com.opensymphony.xwork2.ActionSupport#execute()
*/
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
try
{
Document doc = new Document();
doc.setTitle(title);
if(content != null)
{
doc.setContent(new ClobImpl(content));
}
super.getAdminService().addDocument(doc);
super.getDataMap().put(JSONConstant.JSON_STATUS, JSONConstant.JSON_STATUS_SUCCESS);
}
catch(Exception e)
{
e.printStackTrace();
super.getDataMap().put(JSONConstant.JSON_STATUS, JSONConstant.JSON_STATUS_ERROR);
}
return SUCCESS;
}

}


关于Service层的依赖代码省略…

附上Struts2相关转换器代码

package com.nytech.struts.converter;

import java.sql.Clob;
import java.sql.SQLException;
import java.util.Map;

import org.apache.struts2.util.StrutsTypeConverter;
import org.hibernate.lob.ClobImpl;

/**
* @author daniel
*
*/
@SuppressWarnings("rawtypes")
public class ClobConverter extends StrutsTypeConverter {

@Override
public Object convertFromString(Map arg0, String[] arg1, Class arg2) {
// TODO Auto-generated method stub
Clob clob = null;
clob = new ClobImpl(arg1[0]);
return clob;
}

@Override
public String convertToString(Map arg0, Object arg1) {
// TODO Auto-generated method stub
String str = "";
if(arg1 instanceof Clob)
{
Clob clob = (Clob) arg1;
try {
str = clob.getSubString(0, (int) clob.length());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return str;
}
}


之后配置一个全局的xwork-properties文件,放置在classpath的根下

java.sql.Clob=com.nytech.struts.converter.ClobConverter
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hibernate struts2
相关文章推荐