package Jdbc;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JdbcClobTest {
private Connection con;
/**
* mflag = true: 传入Connection
* mflag = false: 不传入Connection
*/
private boolean mflag = false;
public void ExeSQL(Connection tConnection)
{
con = tConnection;
mflag = true;
}
public void ExeSQL()
{
}
/**
* 内容过长超过4000字符 需要向数据库中插入大对象来保存内容
* 此方法 提供底层对数据库大对象的操作支持 目前仅支持oracle
* oracle数据库可以强制把字符串插入到字符大对象中 此方法仅支持更新大对象
* TODO 下面封装的操作oracle大对象的方法还需要完善!!!!!!
*
* 输入:预编译sql和需要的参数 在ExeSQL类初始化的时候建立连接。
* 输出:如果成功执行,返回True,否则返回False,并且在Error中设置错误的详细信息
* @param sql String
* @param params String[]
* @return boolean
*/
/**
* 此方法用于执行对大对象进行操作的sql语句
* 传入的参数:sql带?号(需要传入参数并且为大对象类型)的sql语句,params参数数组,用params中的元素替换sql中的?号
*/
public boolean execUpdateClobSQL(String sql, String[] params){
PreparedStatement pstmt = null;
StringReader reader = null;
System.out.println("预编译ExecSQL执行时间:"+new java.util.Date()+"; ExecSQL : " + sql);
if (!mflag){
con = DBConn.getConn();
}
try{
pstmt = con.prepareStatement(sql);
//循环传入的参数数据 将数组内的参数 赋值给 预编译sql
for (int i = 0; i < params.length; i++) {
System.out.println("传入参数:"+params[i]+" 的对象类型:"+params[i].getClass().getName());
reader = new StringReader(params[i]);
pstmt.setCharacterStream(i+1, reader,params[i].length());
System.out.println("reader = " + reader);
}
pstmt.execute();
pstmt.close();
if (!mflag){
con.commit();
con.close();
}
}
catch (SQLException e){
// @@错误处理
System.out.println("### Error ExeSQL at execUpdateSQL: " + sql);
try{
if (pstmt != null){
//由于描述的问题,导致执行的sql错误百出,因此pstmt的关闭需要特殊处理
try{
pstmt.close();
}
catch (SQLException ex){
ex.printStackTrace();
}
finally{
try{
System.out.println("Sql's bug is very big: " + sql);
pstmt.close();
}
catch (SQLException ex){}
}
}
if (!mflag){
con.rollback();
con.close();
}
}
catch (SQLException ex){
//在这个地方,有可能会没有关闭连接
ex.printStackTrace();
return false;
}
return false;
}finally{
reader.close();
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return true;
}
/***
*
* 更新oracle的CLOB字段 上面的方法只能做插入带有CLOB的操作
* @param sql String 例如:select workjson from tbl_lwprocess where processid = ? for update
* @param params String[] 此处为?需要的值
* @param toClobString 需要写入大对象字段的字符串
* @return boolean
*/
public boolean updateClob(String sql, String[] params, String toClobString){
PreparedStatement pstmt = null;
ResultSet rs = null;
Writer write = null;
oracle.sql.CLOB clob = null;
//System.out.println("下面是预编译ExecSQL...");
System.out.println("预编译ExecSQL执行时间:"+new java.util.Date()+"; ExecSQL : " + sql);
try{
if (!mflag){
con = DBConn.getConn();
con.setAutoCommit(false);
}
pstmt = con.prepareStatement(sql);
//循环传入的参数数据 将数组内的参数 赋值给 预编译sql modified by guodanlong at 2012-05-28
for (int i = 0; i < params.length; i++) {
System.out.println("传入参数:"+params[i]+" 的对象类型:"+params[i].getClass().getName());
pstmt.setObject(i+1, params[i]);
}
rs = pstmt.executeQuery();
if(rs.next())
{
clob = (oracle.sql.CLOB)rs.getClob(1);
}
write = clob.getCharacterOutputStream();
write.write(toClobString);
write.flush();
write.close();
rs.close();
pstmt.close();
if (!mflag){
con.commit();
con.close();
}
}
catch (Exception e){
// @@错误处理
System.out.println("### Error ExeSQL at execUpdateSQL: " + sql);
try{
if (pstmt != null){
//由于描述的问题,导致执行的sql错误百出,因此pstmt的关闭需要特殊处理
try{
pstmt.close();
}
catch (SQLException ex){
ex.printStackTrace();
}
finally{
try{
System.out.println("Sql's bug is very big: " + sql);
pstmt.close();
}
catch (SQLException ex){}
}
}
if (!mflag){
con.rollback();
con.close();
}
}
catch (SQLException ex){
//在这个地方,有可能会没有关闭连接
ex.printStackTrace();
return false;
}
return false;
}finally{
try {
write.close();
pstmt.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
/***
* 支持系统底层获取数据库大对象内容
* 每次只能获取一个大对象字段的全部内容
* 后续如有需要获取部分大对象内容请重载此方法
* 目前仅支持oracle
*
* 预编译sql执行查询,将预编译的sql查询结果返回!
* @param sql String //预编译sql
* @param params Object[] //预编译sql需要的参数
* @return String //返回预编译sql和参数组合后的sql命令执行后的结果集
* */
public String execClobSQL(String sql ,Object[] params)
{
PreparedStatement pstmt = null;
ResultSet rs = null;
String clobStr = "";
System.out.println("预编译ExecSQL执行时间:"+new java.util.Date()+"; ExecSQL : " + sql);
if (!mflag)
{
con = DBConn.getConn();
}
try
{
pstmt = con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY
, ResultSet.CONCUR_READ_ONLY);
//循环传入的参数数据 将数组内的参数 赋值给 预编译sql modified by guodanlong at 2012-05-28
for (int i = 0; i < params.length; i++) {
System.out.println("传入参数:"+params[i]+" 的对象类型:"+params[i].getClass().getName());
pstmt.setObject(i+1, params[i]);
}
rs = pstmt.executeQuery();
/**
* 下面将结果集中的大对象流 读出并拼装成字符串返回
* 如果有记录去取出大对象的内容并处理
* 如果有记录 大对象的内容没有 则直接返回
*/
if (rs.next())
{
java.sql.Clob clob = rs.getClob(1);
if(clob == null){//如果大对象字段为空 则直接返回""字符串
return clobStr;
}
Reader inStream = clob.getCharacterStream();
char[] c = new char[(int) clob.length()];
try {
inStream.read(c);
clobStr = new String(c);
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
//clobStr是读出并需要返回的数据,类型是String
}
rs.close();
pstmt.close();
if (!mflag)
{
con.close();
}
}
catch (SQLException e)
{
System.out.println("### Error ExeSQL at execSQL(String sql): " + sql);
e.printStackTrace();
// @@错误处理
try
{
if (rs != null)
{
rs.close();
}
if (pstmt != null)
{
//由于描述的问题,导致执行的sql错误百出,因此pstmt的关闭需要特殊处理
try
{
pstmt.close();
}
catch (SQLException ex)
{
ex.printStackTrace();
}
finally
{
try
{
System.out.println("Sql's bug is very big: " + sql);
pstmt.close();
}
catch (SQLException ex)
{}
}
}
if (!mflag)
{
con.close();
}
}
catch (SQLException ex)
{
ex.printStackTrace();
}
}
return clobStr;
}
public static void main(String[] args) {
JdbcClobTest jdbcClobTest=new JdbcClobTest();
//查询CLOB字段
String cxsql = "select workjson from tbl_lwprocess";
String content = jdbcClobTest.execClobSQL(cxsql,new String[] {});
System.out.println(content);
//插入
String crsql = "insert into tbl_lwprocess (processid,workjson) values ('001',?) ";
String[] crparams={"123测试大字符串"};
jdbcClobTest.execUpdateClobSQL(crsql, crparams);
content = jdbcClobTest.execClobSQL(cxsql,new String[] {});
System.out.println(content);
//更新
String gxsql = "select workjson from tbl_lwprocess where 1 = ? for update ";
String workjson = "{111naasdfasdfasdfasdfasdfasdfasdfme':null,'count':3,'nodes':[{'id':'node_1','name':'0000000010','type':'node','shape':'rect','number':1,'left':100,'top':80,'width':100,'height':40,'property':[{'id':'n_p_name','text':'select','value':'0000000010'}]},{'id':'node_2','name':'0000000003','type':'node','shape':'rect','number':2,'left':145,'top':193,'width':100,'height':40,'property':[{'id':'n_p_name','text':'select','value':'0000000003'}]}],'lines':[{'id':'line_3','name':'001','type':'line','shape':'line','number':3,'from':'node_1','to':'node_2','fromx':150,'fromy':120,'tox':145,'toy':193,'polydot':[],'property':[{'id':'l_p_id','text':'span','value':'line_3'},{'id':'l_p_name','text':'}]}]} f";
String[] params={"1"};
jdbcClobTest.updateClob(gxsql, params, workjson);
content = jdbcClobTest.execClobSQL(cxsql,new String[] {});
System.out.println(content);
}
}