Error Log:
11:21:56.761 [CSXML-APP-ThreadPool-26] ERROR c.c.m.w.MCMTaskProcessTemplate - fail_to_submit_task:83291896
org.springframework.jdbc.UncategorizedSQLException: SqlMapClient operation; uncategorized SQLException for SQL []; SQL state [72000]; error code [1465];
--- The error occurred in META-INF/config/sql-mapping/sql.xml.
--- The error occurred while applying a parameter map.
--- Check the infoPublishPlanAdd-InlineParameterMap.
--- Check the statement (update failed).
--- Cause: java.sql.SQLException: ORA-01465: 无效的十六进制数字
; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in META-INF/config/sql-mapping/sql.xml.
--- The error occurred while applying a parameter map.
--- Check the infoPublishPlanAdd-InlineParameterMap.
--- Check the statement (update failed).
--- Cause: java.sql.SQLException: ORA-01465: 无效的十六进制数字
原因是在往数据库中,插入BLOB字段时出错。
XXXRequest.java
private String content;
public void setContent(String content){
this.content=content;
}
public String getContent(){
return this.content;
}
XXXServiceImpl.java
public XXXResponse submit(XXXRequest request){
...
Map map = new HashMap();
map.put(... , ...);
...
map.put("Content",request.getContent());
...
this.sqlMap.insert("XXXinsert",map);//一个数据库插入操作
return null;
}
XXXsql.xml
...
insert into XXXXtable
(
...
CONTENT,
...
)
values
(
...
#Content#,
...
)
...
CONTENT是一个类型为BLOB的字段,
然后,运行程序,在插入操作时,就出现了本文最开始的那一段Error Log.
ORA-01465:无效的十六进制数字。。。
错误原因是因为程序中Content是String类型的,插入Blob类型的字段中,出现的这个错误。解决的办法:是先将待插入的Content转化成二进制数据,
然后插入数据时,加上to_blob即可。。。。
insert into XXXtable(CONTENT) values(to_blob(二进制数据))
我用的公司的处理方式来实现BLOB数据的插入在XXXServiceImpl.java中
public XXXResponse submit(XXXRequest request){
...
Map map = new HashMap();
map.put(... , ...);
...
map.put("Content",FileUtil.format(request.getContent().getBytes()).getBytes());//其实我不是很明白FileUtil.format的这个作用何在
...
this.sqlMap.insert("XXXinsert",map);//一个数据库插入操作
return null;
}
然后sql脚本中插入时,并没有使用to_blob(所以我很困惑,也很好奇to_blob这个方法做了什么操作,很可惜oracle没有公布源码,网上也搜不到to_blob的用法以及作用)
废话不多说,继续之前的问题,在上面的impl中,使用FileUtil.format将二进制序列转化成string,然后又将这个string转化为二进制,一直不明白为什么这样转来转去~(公司的这么做,肯定有他的作用,接下来继续看…..)
FileUtil.java 中的format方法
static public String format(byte[] saveItem) throws IOException
{
StringBuffer resultBuffer = new StringBuffer();
if(log.isDebugEnabled())
{
log.debug("before format: "+saveItem);
}
byte xmlData[] = saveItem;
if(log.isDebugEnabled())
{
log.debug("after format: "+new String(xmlData));
}
// sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
if (xmlData.length >= 200) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
GZIPOutputStream gzout = new GZIPOutputStream(bout);
gzout.write(xmlData);
gzout.finish();
byte result[] = bout.toByteArray();
resultBuffer.append('Z');
resultBuffer.append(Base64.byteArrayToBase64(result));
} else {
resultBuffer.append('N');
resultBuffer.append(Base64.byteArrayToBase64(xmlData));
}
System.err.println("_________"+resultBuffer.toString());
return resultBuffer.toString();
// return URLEncoder.encode(resultBuffer.toString(), "8859_1");
}
这个里面的那个关于压缩标记那个,我们不管,其实这个format主要的就是Base64.byteArrayToBase64(xmlData)这个操作,将一个bytes数组转化为Base64类型的东东。。。
然后问题来了,Base64又是一个什么鬼?
So…..
Base64编码相关如下:
把byte[]中的元素当做无符号八位整数转换成只含有64个基本字符的字符串,这些基本字符是:
l 大写的A-Z
l 小写的a-z
l 数字0-9
l ‘+’ 和 ‘/’
这64个字符构成BASE64的字符集。‘=’,为填充字符,结尾处可以填充0-2个填充字符
Base64是将原文按照每 3 个字节一组分开,这个 3 字节组中的每一组将被按照位分解成 4 个部分,每个部分 6 个位,在这 4 个部分的每个部分高位加上 2 个 0构成一个新的 4 字节组,新的字节组中,每个字节只有 6 位,能表示64个值。
在原文在转换为BASE64编码时,试是以3个字节为一组转换成4字节一组的BASE64编码。如果原文不是三字节的倍数,可能多出一个字节和两个字节,分别会被转为2字节和3字节的BASE64编码,这时编码系统应该在形成的BASE64编码最后添加上填充符”=”,保证BASE64编码长度是4的倍数。所以在BASE64编码后添加的填充符”=”可能为0-2个。
BASE64编码对照表如下:
Value | Encoding | Value | Encoding | Value | Encoding | Value | Encoding |
---|---|---|---|---|---|---|---|
0 | A | 16 | Q | 32 | g | 48 | w |
1 | B | 17 | R | 33 | h | 49 | x |
2 | C | 18 | S | 34 | i | 50 | y |
3 | D | 19 | T | 35 | j | 51 | z |
4 | E | 20 | U | 36 | k | 52 | 0 |
5 | F | 21 | V | 37 | l | 53 | 1 |
6 | G | 22 | W | 38 | m | 54 | 2 |
7 | H | 23 | X | 39 | n | 55 | 3 |
8 | I | 24 | Y | 40 | o | 56 | 4 |
9 | J | 25 | Z | 41 | p | 57 | 5 |
10 | K | 26 | a | 42 | q | 58 | 6 |
11 | L | 27 | b | 43 | r | 59 | 7 |
12 | M | 28 | c | 44 | s | 60 | 8 |
13 | N | 29 | d | 45 | t | 61 | 9 |
14 | O | 30 | e | 46 | u | 62 | + |
15 | P | 31 | f | 47 | v | 63 | / |
Byte[]和BASE64之间的转换纯粹就是表现形式的一种转换,它们之间有直接的对应关系,不涉及到使用何种代码页的问题,BASE64表达的也是字节流。
然,,,,反编译了Base64.byteArrayToBase64(xmlData)这个方法的代码,本来准备研究一下下~
/* */ package com.xxxxxx.util;
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public class Base64
/* */ {
/* */ public Base64() {}
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public static String byteArrayToBase64(byte[] a)
/* */ {
/* 33 */ return byteArrayToBase64(a, false);
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public static String byteArrayToAltBase64(byte[] a)
/* */ {
/* 43 */ return byteArrayToBase64(a, true);
/* */ }
/* */
/* */ private static String byteArrayToBase64(byte[] a, boolean alternate) {
/* 47 */ int aLen = a.length;
/* 48 */ int numFullGroups = aLen / 3;
/* 49 */ int numBytesInPartialGroup = aLen - 3 * numFullGroups;
/* 50 */ int resultLen = 4 * ((aLen + 2) / 3);
/* 51 */ StringBuffer result = new StringBuffer(resultLen);
/* 52 */ char[] intToAlpha = alternate ? intToAltBase64 : intToBase64;
/* */
/* */
/* 55 */ int inCursor = 0;
/* 56 */ for (int i = 0; i < numFullGroups; i++) {
/* 57 */ int byte0 = a[(inCursor++)] & 0xFF;
/* 58 */ int byte1 = a[(inCursor++)] & 0xFF;
/* 59 */ int byte2 = a[(inCursor++)] & 0xFF;
/* 60 */ result.append(intToAlpha[(byte0 >> 2)]);
/* 61 */ result.append(intToAlpha[(byte0 << 4 & 0x3F | byte1 >> 4)]);
/* 62 */ result.append(intToAlpha[(byte1 << 2 & 0x3F | byte2 >> 6)]);
/* 63 */ result.append(intToAlpha[(byte2 & 0x3F)]);
/* */ }
/* */
/* */
/* 67 */ if (numBytesInPartialGroup != 0) {
/* 68 */ int byte0 = a[(inCursor++)] & 0xFF;
/* 69 */ result.append(intToAlpha[(byte0 >> 2)]);
/* 70 */ if (numBytesInPartialGroup == 1) {
/* 71 */ result.append(intToAlpha[(byte0 << 4 & 0x3F)]);
/* 72 */ result.append("==");
/* */ }
/* */ else {
/* 75 */ int byte1 = a[(inCursor++)] & 0xFF;
/* 76 */ result.append(intToAlpha[(byte0 << 4 & 0x3F | byte1 >> 4)]);
/* 77 */ result.append(intToAlpha[(byte1 << 2 & 0x3F)]);
/* 78 */ result.append('=');
/* */ }
/* */ }
/* */
/* */
/* 83 */ return result.toString();
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* 91 */ private static final char[] intToBase64 = {
/* 92 */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
/* 93 */ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
/* 94 */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
/* 95 */ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
/* 96 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 106 */ private static final char[] intToAltBase64 = {
/* 107 */ '!', '"', '#', '$', '%', '&', '\'', '(', ')', ',', '-', '.', ':',
/* 108 */ ';', '<', '>', '@', '[', ']', '^', '`', '_', '{', '|', '}', '~',
/* 109 */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
/* 110 */ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
/* 111 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '?' };
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public static byte[] base64ToByteArray(String s)
/* */ {
/* 122 */ return base64ToByteArray(s, false);
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public static byte[] altBase64ToByteArray(String s)
/* */ {
/* 134 */ return base64ToByteArray(s, true);
/* */ }
/* */
/* */ private static byte[] base64ToByteArray(String s, boolean alternate) {
/* 138 */ byte[] alphaToInt = alternate ? altBase64ToInt : base64ToInt;
/* 139 */ int sLen = s.length();
/* 140 */ int numGroups = sLen / 4;
/* 141 */ if (4 * numGroups != sLen)
/* 142 */ throw new IllegalArgumentException(
/* 143 */ "String length must be a multiple of four.");
/* 144 */ int missingBytesInLastGroup = 0;
/* 145 */ int numFullGroups = numGroups;
/* 146 */ if (sLen != 0) {
/* 147 */ if (s.charAt(sLen - 1) == '=') {
/* 148 */ missingBytesInLastGroup++;
/* 149 */ numFullGroups--;
/* */ }
/* 151 */ if (s.charAt(sLen - 2) == '=')
/* 152 */ missingBytesInLastGroup++;
/* */ }
/* 154 */ byte[] result = new byte[3 * numGroups - missingBytesInLastGroup];
/* */
/* */
/* 157 */ int inCursor = 0;int outCursor = 0;
/* 158 */ for (int i = 0; i < numFullGroups; i++) {
/* 159 */ int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
/* 160 */ int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
/* 161 */ int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
/* 162 */ int ch3 = base64toInt(s.charAt(inCursor++), alphaToInt);
/* 163 */ result[(outCursor++)] = ((byte)(ch0 << 2 | ch1 >> 4));
/* 164 */ result[(outCursor++)] = ((byte)(ch1 << 4 | ch2 >> 2));
/* 165 */ result[(outCursor++)] = ((byte)(ch2 << 6 | ch3));
/* */ }
/* */
/* */
/* 169 */ if (missingBytesInLastGroup != 0) {
/* 170 */ int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
/* 171 */ int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
/* 172 */ result[(outCursor++)] = ((byte)(ch0 << 2 | ch1 >> 4));
/* */
/* 174 */ if (missingBytesInLastGroup == 1) {
/* 175 */ int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
/* 176 */ result[(outCursor++)] = ((byte)(ch1 << 4 | ch2 >> 2));
/* */ }
/* */ }
/* */
/* */
/* 181 */ return result;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private static int base64toInt(char c, byte[] alphaToInt)
/* */ {
/* 192 */ int result = alphaToInt[c];
/* 193 */ if (result < 0)
/* 194 */ throw new IllegalArgumentException("Illegal character " + c);
/* 195 */ return result;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 205 */ private static final byte[] base64ToInt = {
/* 206 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 207 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 208 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
/* 209 */ 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
/* 210 */ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
/* 211 */ 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
/* 212 */ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 };
/* */
/* */
/* */
/* */
/* */
/* */
/* 219 */ private static final byte[] altBase64ToInt = {
/* 220 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 221 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1,
/* 222 */ 2, 3, 4, 5, 6, 7, 8, -1, 62, 9, 10, 11, -1, 52, 53, 54, 55, 56, 57,
/* 223 */ 58, 59, 60, 61, 12, 13, 14, -1, 15, 63, 16, -1, -1, -1, -1, -1, -1,
/* 224 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 225 */ -1, -1, -1, 17, -1, 18, 19, 21, 20, 26, 27, 28, 29, 30, 31, 32, 33,
/* 226 */ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
/* 227 */ 51, 22, 23, 24, 25 };
/* */ }
/* Location: /Users/Derek/Documents/workspace/xxxxxxxx.jar
* Qualified Name: XXXXXXXX----
* Java Class Version: 5 (49.0)
* JD-Core Version: 0.7.0.1
*/
然后看的我心累,最后就放弃去研究这段代码了,不过大致看起来好像和前面Base64的编码规则一样。。。。
最后,我还是想说,oracle的to_blob(‘binary code’)这个方法的作用到底是什么?有人可以帮忙解释一下吗?