收藏 分享(赏)

Oracle Clob应用说明.docx

上传人:dreamzhangning 文档编号:2605327 上传时间:2018-09-23 格式:DOCX 页数:34 大小:225.24KB
下载 相关 举报
Oracle Clob应用说明.docx_第1页
第1页 / 共34页
Oracle Clob应用说明.docx_第2页
第2页 / 共34页
Oracle Clob应用说明.docx_第3页
第3页 / 共34页
Oracle Clob应用说明.docx_第4页
第4页 / 共34页
Oracle Clob应用说明.docx_第5页
第5页 / 共34页
点击查看更多>>
资源描述

1、最近利用 NHibernate 映射类型为 Clob 字段在插入数据时发现当字符的字节数(一个半角字符一个字节,一个全角字符两个字节)在 2000-4000 之间时报错(ORA-01461: 仅可以插入 LONG 列的 LONG 值赋值)。经过不断查找资料和自己的试验该问题终于得到解决,下边我将自己的心得给大家做一个分享。准备系统环境 xp+.net2.0+oracle9i表结构(由于是测试,表结构随便建了一张) XX 字段名 类型ID VARCHAR2(70)TEST CLOB测试方式 1:直接将 CLOB 的值拼写在 SQL 语句中。代码:1. string id = Guid.NewGu

2、id().ToString();2. OracleCommand cmd = Conn.CreateCommand();3. cmd.CommandText = “insert into xx(id,test) values(“ + id + “,“ + data + “)“;/ data 是一个变量,存储你要插入的字符串4. cmd.ExecuteNonQuery();5.情况分析:当 data 的长度大于 4000 时报错(ORA-01704:文字字符串过长),小于或等于4000 时正常插入。原因分析:之所以会出现长度大于 4000 时报错,是因为 Oracle 中有 SQL 语句中两个单

3、引号之间的字符数不能大于 4000 的限制。“ + data + “ data 在 sql 语句之间,当 data 的值大于 4000 个字节时就会报错。解决办法:这种方式比较棘手,但有更好的方式,下边会讲到 。方式 2:采用参数形式。代码:1. string id = Guid.NewGuid().ToString();2. OracleCommand cmd = Conn.CreateCommand();3. cmd.CommandText = “insert into xx(id,test) values(“ + id + “,:p1)“;4. OracleParameter p1 =

4、new OracleParameter(“p1“, OracleType.Clob);5. p1.Value = data; / data 是一个变量,存储你要插入的字符串6. cmd.Parameters.Add(p1);7. cmd.ExecuteNonQuery();情况分析:采用这种方式能够正常插入。所以推荐用这种方式。原因分析:无解决办法:无方式 3:采用参数形式,但是参数类型写为 OracleType. NVarChar代码:1. string id = Guid.NewGuid().ToString();2. OracleCommand cmd = Conn.CreateComm

5、and();3. cmd.CommandText = “insert into xx(id,test) values(“ + id + “,:p1)“;4. OracleParameter p1 = new OracleParameter(“p1“, OracleType. NVarChar);5. p1.Value = data; / data 是一个变量,存储你要插入的字符串 6. cmd.Parameters.Add(p1);7. cmd.ExecuteNonQuery();8.情况分析:为什么要写这种方式,因为这种方式和采用 NHibernate 的方式很相似,先看看在这种方式会产生什

6、么情况。 当 data 的字节数在 0-2000 之间时正常插入,大于 4000 时也正常插入,但在 2000-4000 时则失败,报错(ORA-01461: 仅可以插入 LONG 列的 LONG 值赋值)原因分析:没有采用对应的 Oracle 类型。解决办法:采用 OracleType.Clob下边采用 NHibernate 插入数据,NHibernate 具体怎用不在本次讨论范围。NHibernate 采用的版本为 1.2.1.4000。下边大至把简要配置写下。App.configxx.cs1. using System;2. using System.Collections.Generi

7、c;3. using System.Text;4.5. namespace Test.Enties6. 7. Serializable8. public class Xx9. 10. public Xx()11. 12. 13.14. private string id;15.16. public virtual string Id17. 18. get return id; 19. set id = value; 20. 21.22. public virtual string Test23. 24. get return test; 25. set test = value; 26. 27

8、.28. private string test;29.30. 31. xx.hbm.xml说明:这里的驱动用的NHibernate.Driver.OracleClientDriver,其实是对微软的 OracleClient 的封装啦,其实内部还是调用微软的 OracleClient 的东东。引用System.Data.OracleClient.dll 即可 OracleClient。做好上边的配置后,便有了以下的方式方式 4:采用 NHibernate代码:1. string id = Guid.NewGuid().ToString();2. Xx xx = new Xx();3. xx.

9、Test = data; / data 是一个变量,存储你要插入的字符串4. xx.Id = id;5. ISession session = SessionFactory.OpenSession();6. session.Save(xx);7. session.Flush();8.情况分析:当 data 的字节数在 0-2000 之间时正常插入,大于 4000 时也正常插入,但在2000-4000 时则失败,报错(ORA-01461:仅可以插入 LONG 列的 LONG 值赋值).情况和方式 3 的情况一样。原因分析:NHibernate 在用 OracleClient 映射 StringC

10、lob 时,设置参数类型为OracleType. NVarChar,导致插入有 BUG。网上有人推测是 OracleClient 的BUG 所致,理由是换用 OracleDataAccess 即可解决。为什么说 NHibernate 将参数类型设置为 OracleType.NVarChar 呢?看下边1. 找到 NHibernate 的源代码,把它加入你的工程。记得不要移动NHibernate 位置直接加入工程,直接在 NHibernate 的安装目录引用进来。2. 在 Test 解决方案中添加 NHibernate 的项目引用。经过上边两个步骤我们就可以跟踪调试 NHibernate 了1.

11、 跟踪代码 session.Save(xx);看看它究竟做了啥。当我们跟进 CommandSetBatchingBatcher 时,可以得到以下信息(如图中的调试信息)。CurrentBatch 类型是OracleClientCommandSet,OracleClientCommandSet 看源码得知是对微软的 OracleCommandSet 的封装,因为这个类 internal sealed class,所以我们的程序里是找不到这个类的,不过 NHibernate 通过反射使用了它的功能。OracleCommandSet 可能用作批处理的,就是一次处理多个 SQL 语句的,不是太了解,谁

12、知道请指教。CommandSetBatchingBatcher 的源码1. internal class OracleClientCommandSet : DbCommandSet2. 3. private static System.Type oracleCmdSetType;4.5. static OracleClientCommandSet()6. 7. Assembly sysDataOracleClient = Assembly.Load(“System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyTok

13、en=b77a5c561934e089“);8. oracleCmdSetType = sysDataOracleClient.GetType(“System.Data.OracleClient.OracleCommandSet“);9. Debug.Assert(oracleCmdSetType != null, “Could not find OracleCommandSet!“);10. 11.12. protected override object CreateInternalCommandSet()13. 14. return Activator.CreateInstance(or

14、acleCmdSetType, true);15. 16.17. 跟踪 CurrentBatch 可以看到CommandText:declaretype refcursortype is ref cursor;beginINSERT INTO z3 (test, id) VALUES (:p2, :p3);:r1_4 := sql%rowcount;end;这里的 p2 就是我们的 Clob 类型字段的参数啦。再看 p2 的 OracleType 是 NVarChar,是不是有点明白啦,对了, 跟我们 3 一样,参数类型错掉了。解决办法:使用 NHibernate 的自定义类型,不是太会,幸好

15、网上有高人提供代码,在此想高人致谢。这样我们通过自定义类型来设置正确的 OracleType 即可。在项目中添加两个类。PatchForOracleLobField.cs1. using System;2. using System.Collections.Generic;3. using System.Data;4. using System.Text;5. using NHibernate;6. using NHibernate.SqlTypes;7. using NHibernate.UserTypes;8.9. namespace Test.type10. 11. public abs

16、tract class PatchForOracleLobField : IUserType12. 13. public PatchForOracleLobField()14. 15. 16.17. public bool IsMutable18. 19. get return true; 20. 21.22. public System.Type ReturnedType23. 24. get return typeof(String); 25. 26.27. public SqlType SqlTypes28. 29. get30. 31. return new SqlType NHibe

17、rnateUtil.String.SqlType ;32. 33. 34.35. public object DeepCopy(object value)36. 37. return value;38. 39.40. public new bool Equals(object x, object y)41. 42. return x = y;43. 44.45. public int GetHashCode(object x)46. 47. return x.GetHashCode();48. 49.50. public object Assemble(object cached, objec

18、t owner)51. 52. return DeepCopy(cached);53. 54.55. public object Disassemble(object value)56. 57. return DeepCopy(value);58. 59.60. public object NullSafeGet(IDataReader rs, string names, object owner)61. 62. return NHibernate.NHibernateUtil.StringClob.NullSafeGet(rs, names0);63. 64.65. public abstr

19、act void NullSafeSet(IDbCommand cmd, object value, int index);66.67. public object Replace(object original, object target, object owner)68. 69. return original;70. 71.72. 73. OracleClobField.cs1. using System;2. using System.Collections.Generic;3. using System.Data;4. using System.Data.OracleClient;

20、5. using System.Text;6.7. namespace Test.type8. 9. public class OracleClobField : PatchForOracleLobField10. 11. public override void NullSafeSet(IDbCommand cmd, object value, int index)12. 13. if (cmd is OracleCommand)14. 15. /CLob、NClob 类型的字段,存入中文时参数的 OracleDbType 必须设置为 OracleDbType.Clob16. /否则会变成乱

21、码(Oracle 10g client 环境)17. OracleParameter param = cmd.Parametersindex as OracleParameter;18. if (param != null)19. 20. param.OracleType = OracleType.Clob;/ 关键就这里啦21. param.IsNullable = true;22. 23. 24. NHibernate.NHibernateUtil.StringClob.NullSafeSet(cmd, value, index);25. 26. 27. 28.然后在映射文件中修改类型即可

22、。Com.Dic.Icqs.Entities.Type.OracleClobField,Com.Dic.Icqs.Entities修改前:修改后:Test.type.OracleClobField 是类的完整名,Test 即 OracleClobField 所在的程序集。oracle 数据库当需要存入大数据量(大于 4000)时,varchar2 不够用,可以使用 clob,本文描述 clob 怎么和 Hibernate 一起使用。以公告 Notice 的公告内容 noticeContent 为例说明:Notice 表 notice_content 字段为 clob 类型;Notice 类的

23、noticeContent 属性为 String;Notice_hbm_xml 映射文件为 text 类型:html view plaincopy1. 2. 3. LOB 数据不能象其它类型数据一样直接插入(INSERT)。 插入前必须先插入一个空的LOB 对象, CLOB 类型的空对象为 EMPTY_CLOB (),BLOB 类型的空对象为EMPTY_BLOB()。之后通过 SELECT 命令查询得到先前插入的记录并锁定,继而将空对象修改为所要插入的LOB 对象。在插入到更新之间一定要将自动提交设为 false,否则,再次查找时就不能正确更新,查找时一定要用 select XXX from

24、table where . for update 如果不加 for update 会报:“row containing the LOB value is not locked”;如果在插入前没有将自动提交设为 false 会报 “fetch out of sequence”。实例如下:java view plaincopy1. StringBuffer sqlstr = new StringBuffer(); 2. sqlstr.append(“INSERT INTO notice t (t.notice_id,t.notice_type,t.notice_title,“ + 3. “t.no

25、tice_status,t.sender,t.eff_date,t.exp_date,t.creater,t.create_time,“ + 4. “t.notice_content) VALUES (“); 5. sqlstr.append(+notice.getNoticeId() + “,“); 6. sqlstr.append(“ + notice.getNoticeType() + “,“); 7. sqlstr.append(“ + notice.getNoticeTitle() + “,“); 8. sqlstr.append(“ + notice.getNoticeStatus

26、() + “,“); 9. sqlstr.append(“ + notice.getSender() + “,“); 10. sqlstr.append(“sysdate,“); 11. sqlstr.append(“to_date(“ + theForm.getEndDate2() + “ 23:59:59,yyyy-MM-dd HH24:mi:ss),“); 12. sqlstr.append(“ + notice.getCreater() + “,“); 13. sqlstr.append(“sysdate,“); 14. sqlstr.append(“empty_clob()“);/插

27、入空值 15. sqlstr.append(“)“); 16. 17. String sql = sqlstr.toString(); 18. Class.forName(driverClassName); 19. Connection con = DriverManager.getConnection(url, username, password);20. con.setAutoCommit(false);/设置不自动提交 21. PreparedStatement pstmt = con.prepareStatement(sql); 22. String content = notice

28、.getNoticeContent().replace(, “); 23. 24. try 25. pstmt.execute(); 26. mit();/插入 27. 28. pstmt = con.prepareStatement(“select notice_content from notice where notice_id=“+notice.getNoticeId()+“ for update“);/查找刚刚插入的那条记录 for update 29. ResultSet res = pstmt.executeQuery(); 30. CLOB clob = null; 31. w

29、hile(res.next() 32. clob = (oracle.sql.CLOB)res.getClob(1); 33. clob.putString(1, content);/content 为前台提交过来的公告内容,大数据量 34. 35. 36. pstmt = con.prepareStatement(“update notice set notice_content = ? where notice_id=?“);/修改 notice_content 字段的内容 37. pstmt.setClob(1, clob); 38. pstmt.setLong(2, notice.ge

30、tNoticeId(); 39. pstmt.executeUpdate(); 40. 41. mit(); 42. 43. if (nps != null 45. 46. 47. catch (Exception e) 48. info.setCode(“1“); 49. info.setFlag(false); 50. info.setInfo(“发布公告失败!“ ); 51. 52. System.out.println(e.getMessage(); 53. System.out.println(e.getStackTrace(); 54. FileLog.errorLog(e, “发

31、布公告失败“ ); 55. return info; 56. finally 57. if(pstmt!=null) 58. pstmt.close(); 59. 60. if(con!=null) 61. con.close(); 62. 63. 64. 对于 clob 的修改,可在修改该表的其他字段信息时同时将 clob 字段修改为EMPTY_CLOB (),然后才对 clob 字段单独修改,方法与上相同。65.66.67. 存入 clob 类型的文字一般很多,页面不会直接使用 textarea,可以使用开源的CKEditor 文字编辑器代替,使用方法很简单很实用,详见: CKEditor

32、 的使用示例CKEditor 是一个专门使用在网页上属于开放源代码的所见即所得文字编辑器。以前叫FCKEditor。1、到官网下载 CKEditor:http:/ ,解压后复制到工程的WEBROOT 目录下。2、新建 JSP 页面,引用其 JS 文件3、用 CKEditor 替代 textarea:请输入 .4、用 CKEditor 替代 textarea,有两种方法,相应的 javascript 代码如下:在 textarea 后面加入 javascript:CKEDITOR.replace(editor01);或在加载后调用响应的方法:window.onload = function()C

33、KEDITOR.replace( editor01 );配置完成,效果如下图:该编辑器是默认配置,显示了所有工具栏,可使只显示需要的工具栏;编辑框的背景颜色等也可以调整。替代 textarea 的 javascript 如下:javascript view plaincopy1. function window.onload() /页面加载完成后执行以下表达式 2. CKEDITOR.replace( noticeContent, 3. 4. uiColor : #ccccff, 5. toolbar : 6. name: document, items : Save,DocProps,Pre

34、view,Print , 7. name: clipboard, items : Cut,Copy,Paste,PasteText,PasteFromWord,-,Undo,Redo , 8. name: editing, items : Find,Replace,-,SelectAll,-,SpellChecker, Scayt , 9. name: basicstyles, items : Bold,Italic,Underline,Strike,Subscript,Superscript,-,RemoveFormat , 10. name: paragraph, items : Numb

35、eredList,BulletedList,-,Outdent,Indent,-,JustifyLeft,JustifyCenter,JustifyRight,JustifyBlock,-,BidiLtr,BidiRtl , 11. name: links, items : Link,Unlink,Anchor , 12. name: insert, items: Table,HorizontalRule,SpecialChar,PageBreak , 13. name: styles, items : Styles,Format,Font,FontSize , 14. name:colors

36、, items : TextColor,BGColor , 15. name: tools, items : Maximize 16. ); 修改后,效果如下:其中 toolbar 的完整内容如下,工具按钮是分组的,一个 name 内的大括号就是一个工具按钮分组,items 后边是具体的按钮,我们可以对这些内容进行适当的删除:javascript view plaincopy1. function window.onload() /页面加载完成后执行以下表达式 2. CKEDITOR.replace( noticeContent, 3. 4. toolbar : 5. name: docume

37、nt, items : Source,-,Save,NewPage,DocProps,Preview,Print,-,Templates , 6. name: clipboard, items : Cut,Copy,Paste,PasteText,PasteFromWord,-,Undo,Redo , 7. name: editing, items : Find,Replace,-,SelectAll,-,SpellChecker, Scayt , 8. name: forms, items : Form, Checkbox, Radio,TextField, Textarea, Select

38、, Button, ImageButton, HiddenField , /, 9. name: basicstyles, items : Bold,Italic,Underline,Strike,Subscript,Superscript,-,RemoveFormat , 10. name: paragraph, items : NumberedList,BulletedList,-,Outdent,Indent,-,Blockquote,CreateDiv, -,JustifyLeft,JustifyCenter,JustifyRight,JustifyBlock,-,BidiLtr,Bi

39、diRtl , 11. name: links, items : Link,Unlink,Anchor , 12. name: insert, items: Image,Flash,Table,HorizontalRule,Smiley,SpecialChar,PageBreak,Iframe , /, 13. name: styles, items : Styles,Format,Font,FontSize , 14. name:colors, items : TextColor,BGColor , 15. name: tools, items : Maximize,ShowBlocks,-

40、,About 16. ); 17. CKEditor 的基本使用就是这样了。Oracle 大文本 clob 数据类型的增删改查package common;import java.io.FileInputStream;import java.io.IOException;import java.io.Reader;import java.io.Writer;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;imp

41、ort java.sql.SQLException;import java.sql.Statement;import java.util.Properties; /* 连接数据库和常用数据库操作的类*/import oracle.sql.CLOB;/* 连接数据库的类* 最基础的类* */public class text /* 连接数据库常用的属性* * */public String sDBDriver = “oracle.jdbc.driver.OracleDriver“;/ 设置驱动public String url = “jdbc:oracle:thin:localhost :spe

42、“;/ 设置数据库信息public String sHint = “;public ResultSet rs = null;public Connection conn = null;public Statement stmt = null;public String user = “study“;public String pwd = “ok“;/* 加载配置文件读取信息* * */public text() throws IOException String userpath = System.getProperty(“user.dir“);String filesparator = S

43、ystem.getProperty(“file.separator“);String dbconfig = userpath + filesparator + “dbconfig.properties“;FileInputStream in;in = new FileInputStream(dbconfig);Properties dbp = new Properties();dbp.load(in);in.close();this.url = dbp.getProperty(“URL“);this.user = dbp.getProperty(“USER“);this.pwd = dbp.g

44、etProperty(“PASSWORD“);System.out.println(“地址=“ + dbconfig);/ System.out.println(“真实=“+this.url);public String getSHint() return sHint;public void setSDBDriver(String dbDriver) sDBDriver = dbDriver;public String getSDBDriver() return sDBDriver;public String getUrl() return url;public void setUrl(Strin

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报