mybatis 插入oracle xmltype型別的資料內容超過4000報錯
資料庫表:
create table BOOK
(
book_id NUMBER not null,
book_name XMLTYPE,
book_price NUMBER
)
JavaBean:
public class Book {
private Integer bookId;
private String bookName;
private Integer bookPrice;
get(),set().......
}
mapper.xml
<insert id="insert" parameterType="com.zfy.db.model.Book" > insert into BOOK (BOOK_ID, BOOK_PRICE, BOOK_NAME ) values (#{bookId}, #{bookPrice,jdbcType=INTEGER}, #{bookName} ) </insert>
JUNIT測試:插入操作
public String getXml() { File file = new File("E:\\test.xml"); InputStream ios = null; StringBuffer xml = new StringBuffer(); try { ios = new FileInputStream(file); byte[] b = new byte[(int) file.length()]; for (int i = 0; i < b.length; i++) { b[i] = (byte) ios.read(); } xml.append(new String(b)); } catch (Exception e) { } finally { try { if (ios != null) ios.close(); } catch (IOException e) { e.printStackTrace(); } } return xml.toString(); } //xmlType型別 @Test public void insertXMLTYPE() throws ParserConfigurationException, SAXException, IOException{ Book book = new Book(); book.setBookId(3); book.setBookName(getXml()); book.setBookPrice(33); session.insert("com.zfy.db.dao.BookMapper.insert",book); session.commit(); session.close(); }
報錯如下:
org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: java.sql.SQLException: ORA-01461: 僅能繫結要插入 LONG 列的 LONG 值
### The error may exist in com/zfy/db/mapping/BookMapper.xml
### The error may involve com.zfy.db.dao.BookMapper.insert-Inline
### The error occurred while setting parameters
### SQL: insert into BOOK (BOOK_ID, BOOK_PRICE, BOOK_NAME ) values (?, ?, ? )
### Cause: java.sql.SQLException: ORA-01461: 僅能繫結要插入 LONG 列的 LONG 值
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:23)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:150)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:137)
at com.zfy.controller.test.ControllerTest.insertXMLTYPE(ControllerTest.java:358)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: java.sql.SQLException: ORA-01461: 僅能繫結要插入 LONG 列的 LONG 值
at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:133)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:206)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:455)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:413)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:1034)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:194)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:953)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1222)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3387)
at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3488)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1374)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:55)
at sun.proxy.$Proxy11.execute(Unknown Source)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:41)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:66)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:59)
at sun.proxy.$Proxy9.update(Unknown Source)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:45)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:100)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:75)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:148)
... 26 more
現在兩種解決方法:
1、用JDBC ,但不適合JDNI資料來源
工具類:XmlTypeUtil.java
package com.zfy.com.util;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import oracle.xml.parser.v2.DOMParser;
public class XmlTypeUtil {
public static org.w3c.dom.Document getDocument(String str) throws Exception{
if(getStr(str).equals("")){
return null;
}
org.w3c.dom.Document doc=null;
try{
DOMParser parser = new DOMParser();
parser.parse(getStringInputString(str));
doc =parser.getDocument();
}catch(Exception e){
e.printStackTrace();
throw e;
}
return doc;
}
/**
* org.w3c.dom.Document -> org.dom4j.Document
*
* @param doc
* Document(org.w3c.dom.Document)
* @return Document
*/
public static org.dom4j.Document parse(org.w3c.dom.Document doc)
throws Exception {
if (doc == null) {
return (null);
}
org.dom4j.io.DOMReader xmlReader = new org.dom4j.io.DOMReader();
return (xmlReader.read(doc));
}
/**
* org.dom4j.Document -> org.w3c.dom.Document
*
* @param doc
* Document(org.dom4j.Document)
* @throws Exception
* @return Document
*/
public static org.w3c.dom.Document parse(org.dom4j.Document doc)
throws Exception {
if (doc == null) {
return (null);
}
java.io.StringReader reader = new java.io.StringReader(doc.asXML());
org.xml.sax.InputSource source = new org.xml.sax.InputSource(reader);
javax.xml.parsers.DocumentBuilderFactory documentBuilderFactory = javax.xml.parsers.DocumentBuilderFactory
.newInstance();
javax.xml.parsers.DocumentBuilder documentBuilder = documentBuilderFactory
.newDocumentBuilder();
return (documentBuilder.parse(source));
}
public static String getStr(Object obj) {
String s = obj == null ? "" : String.valueOf(obj);
if (s.equals("null")) {
return "";
}
return s;
}
public static InputStream getStringInputString(String str)
throws UnsupportedEncodingException {
InputStream f = new ByteArrayInputStream(getStr(str).getBytes("GBK"));
return f;
}
}
JDBC插入一條xml超過4000字元的資料到資料庫
public void insertXmlContent(String fileId, String xmlContent) throws Exception {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = java.sql.DriverManager.getConnection("jdbc:oracle:thin:@192.168.1.252:1521:orcl","dsci","dsci");
OraclePreparedStatement stmt = null;
Document doc = XmlTypeUtil.getDocument(xmlContent);
String sql = "insert into dsc_pro_xml_t0d0(xml_content) values (?)";
stmt = (OraclePreparedStatement) conn.prepareStatement(sql);
XMLType xmlTypeContent = null;
xmlTypeContent = XMLType.createXML(conn, doc);
stmt.setObject(1, xmlTypeContent);
stmt.executeUpdate();
}
方法二:使用臨時表的辦法實現(未測試),這種比較麻煩,但不用考慮資料來源問題
先建立一個臨時的表,其中的一個欄位是clob型別;
再將要寫入xmltype欄位的xml doc寫入這個臨時的clob型的欄位中;
最後insert into abc (id,xmldoc) values (abc_q.nextval , sys.xmlType.createXML((select content from 臨時表 where id=......)));