序列化存取数据库(spring+mybatis+oracle) 以及可能会遇到的数据库取出的数据反序列化失败问题
1.需要序列化的类需要实现Serializable方法
例如下面需要序列化的类
1 import java.io.Serializable; 2 3 public class Topic implements Serializable{ 4 private static final long serialVersionUID = 1L; 5 private Integer id; 6 private String topic; 7 private byte[] messageData; 8 9 public byte[] getMessageData(){ 10 return messageData; 11 } 12 public void setMessageData(String messageData){ //其中messageData是在数据库中以CLOB字段存储的,将类序列化后存入二进制数组 13 this.messageData = HexTool.decode(messageData);
//将数据库中取出的CLOB数据类型,实则为二进制数组字符串String进行解码(十六进制字符串-->byte[]) 否则mybatis取出来的字符串无法反序列化!!!!! 14 } 15 public Integer getId() { 16 return id; 17 } 18 public void setId(Integer id) { 19 this.id = id; 20 } 21 public String getTopic() { 22 return topic; 23 } 24 public void setTopic(String topic) { 25 this.topic = topic; 26 } 27 @Override 28 public String toString() { 29 return "Topic [id=" + id + ", topic=" + topic + "]"; 30 } 31 public Topic(Integer id, String topic) { 32 super(); 33 this.id = id; 34 this.topic = topic; 35 } 36 public Topic() { 37 super(); 38 // TODO Auto-generated constructor stub 39 } 40 }
public class HexTool{ //解码:十六进制字符串转换为byte[] public static byte[] decode(String hexString) { if((hexString.length()%2)!=0) { throw new IllegalArgumentException("A HexBinary string must have even length"); } byte[] result = new byte[hexString.length()/2]; int j = 0; for(int i=0;i<hexString.length();) { byte b; char c = hexString.charAt(i++); char d = hexString.charAt(i++); if(c > = '0' && c<='9') { b = (byte)((c - '0') << 4); }else if(c > = 'A' && c <= 'F') { b=(byte)((c-'A'+10)<<4); }else if(c >= 'a' && c<='f') { b=(byte)((c-'a'+10)<<4); }else { throw new IllegalArgumentException("Invalid hex digit:" + c); } result[j++] = b; } return result; } }
1 public class MessageData { 2 3 private String destinationChannel; 4 5 private String messageId; 6 7 private Date absTime; 8 9 public String getDestinationChannel() { 10 return destinationChannel; 11 } 12 13 public void setDestinationChannel(String destinationChannel) { 14 this.destinationChannel = destinationChannel; 15 } 16 17 public String getMessageId() { 18 return messageId; 19 } 20 21 public void setMessageId(String messageId) { 22 this.messageId = messageId; 23 } 24 25 public Date getAbsTime() { 26 return absTime; 27 } 28 29 public void setAbsTime(Date absTime) { 30 this.absTime = absTime; 31 } 32 33 @Override 34 public String toString() { 35 return "MessageData [destinationChannel=" + destinationChannel + ", messageId=" + messageId + ", absTime=" 36 + absTime + "]"; 37 } 38 39 }
2.将类序列化后写入二进制数组存入数据库,再取出来反序列化
1 import java.io.ByteArrayInputStream; 2 import java.io.ByteArrayOutputStream; 3 import java.io.IOException; 4 import java.io.ObjectInputStream; 5 import java.io.ObjectOutputStream; 6 7 8 @RunWith(SpringRunner.class) 9 @SpringBootTest(classes=启动类.class) 10 public class SerializeTest { 11 12 public static final String INSERTSTOREMESSAGE = "storefoward.intoresendmessage"; 13 public static final String SELECTRESENDMESSAGE = "storefoward.selectresendmessage"; 14 15 @Test 16 public void serializeTest() throws IOException,ParseException,ApplicationNotFoundException,ClassNotFoundException{ 17 18 ByteArrayOutputStream bos = null; 19 ObjectOutputStream oos =null; 20 byte[] serializeTranslateMessage =null; 21 22 MessageData message = MessageData(); 23 24 message.setDestinationChannel("ABC"); 25 message.setmessageId("1433"); 26 message.setabsTime("2019.04.01 10:57:34"); 27
//以下是将类序列化成二进制数组存入数据库 28 try { 29 oos = new ObjectOutputStream(bos=new ByteArrayOutputStream()); 30 oos.writeObject(message); 31 }finally { 32 serializeTranslateMessage = bos.toByteArray(); 33 try { 34 oos.close(); 35 bos.close(); 36 }catch(IOException e) { 37 e.printStackTrace(); 38 } 39 } 40 41 Map<String,Object> map = new HashMap<>; 42 43 map.put("id","1"); 44 map.put("topic","method1"); 45 map.put("messageData",serializeTranslateMessage) //其中messageData在数据库是以CLOB字段存储 46 try { 47 int result = DBUtil.insert(INSERTSTOREMESSAGE,map); 48 }catch(){ 49 e.printStackTrace(); 50 } 51 52 //以上是序列化Topic类并存入数据库的操作 53 54 //以下是从数据库中取出Topic并反序列化 55 56 List<Topic>queryTopicList = null ; 57 Map<String,Object> map2 = new HashMap<>; 58 59 map2.put("id","1"); 60 map2.put("topic","method1"); 61 try { 62 queryTopicList = DBUtil.selectList(SELECTRESENDMESSAGE,map2); 63 }catch(Exception e) { 64 e.printStackTrace(); 65 } 66 67 ObjectInputStream ois = null; 68 ByteArrayInputStream bas = null; 69 for(int j=0;j<queryTopicList.size();j++) { 70 Topic tmpMessage=queryTopicList.get(j); 71 try{ 72 ois = new ObjectInputStream(bas=new ByteArrayInputStream(tmpMessage.getMessageData())); 73 Topic deserializeMessage=(Topic)ois.readObject(); //将反序列化后的数据实例化为Topic类 74 }catch(IOException e) { 75 e.printStackTrace(); 76 try { 77 ois.close(); 78 bas.close(); 79 } 80 catch(IOException E) { 81 E.printStackTrace(); 82 } 83 } 84 85 } 86 87 } 88 }
3.mybatis中语句为
1 <select id = "selectresendmessage" resultType="路径.Topic" parameterType = "java.util.Map"> 2 SELECT 3 ID, 4 TOPIC, 5 MESSAGEDATA 6 FROM 7 STORE_MESSAGE 8 WHERE 9 ID = #{id} 10 AND 11 TOPIC = #{topic} 12 </select> 13 14 <insert id = "intoresendmessage"> 15 INSERT 16 INTO STORE_MESSAGE 17 VALUES(#{id},#{topic},#{messageData} 18 ) 19 </insert>