java对象序列化并存储到文件和数据库

Java中要实现将对象保存起来持久化,需要让对象实现Serializable接口,这样就能将java对象用二进制流保存并恢复。下面我将以保存到文件和保存到mysql来进行解析。先给出序列化类的定义:

  1. package model;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.Date;  
  5. /*  
  6.  * 实现可序列化接口  
  7.  */  
  8. public class Person implements Serializable{  
  9.     private String name;                                 //名字  
  10.     private int year;                                    //年龄  
  11.     private String city;                                 //城市  
  12.     private Date birth;                                  //生日  
  13.       
  14.     public String getName() {  
  15.         return name;  
  16.     }  
  17.     public void setName(String name) {  
  18.         this.name = name;  
  19.         this.year=year;  
  20.         this.city=city;  
  21.     }  
  22.     public int getYear() {  
  23.         return year;  
  24.     }  
  25.     public void setYear(int year) {  
  26.         this.year = year;  
  27.     }  
  28.     public String getCity() {  
  29.         return city;  
  30.     }  
  31.     public void setCity(String city) {  
  32.         this.city = city;  
  33.     }  
  34.       
  35.       
  36.     public Date getBirth() {  
  37.         return birth;  
  38.     }  
  39.     public void setBirth(Date birth) {  
  40.         this.birth = birth;  
  41.     }  
  42.     /*  
  43.      * (non-Javadoc)  
  44.      * @see java.lang.Object#toString()  
  45.      * 重写toString,不然序列化之后显示的是内存地址  
  46.      */  
  47.     public String toString(){  
  48.         return this.name+" "+this.year+" "+this.city+" "+this.birth.toString();  
  49.     }  
  50. }  
package model;

import java.io.Serializable;
import java.util.Date;
/*
 * 实现可序列化接口
 */
public class Person implements Serializable{
	private String name;                                 //名字
	private int year;                                    //年龄
	private String city;                                 //城市
	private Date birth;                                  //生日
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
		this.year=year;
		this.city=city;
	}
	public int getYear() {
		return year;
	}
	public void setYear(int year) {
		this.year = year;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	
	
	public Date getBirth() {
		return birth;
	}
	public void setBirth(Date birth) {
		this.birth = birth;
	}
	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 * 重写toString,不然序列化之后显示的是内存地址
	 */
	public String toString(){
		return this.name+" "+this.year+" "+this.city+" "+this.birth.toString();
	}
}



1.保存对象到文件并恢复
要保存到文件首先必须得获得文件输入流,然后将文件输入流作为参数,构造对象输入流,然后就能直接将对象输入到文件中。而要将对象恢复,则需要先获得文件输出流,然后将文件输出流作为参数,构造对象输出流,就能够得到对象,然后再强制性转换为原始对象即可,实现代码如下:

  1. package saveobject;  
  2.   
  3. import java.io.FileInputStream;  
  4. import java.io.FileNotFoundException;  
  5. import java.io.FileOutputStream;  
  6. import java.io.IOException;  
  7. import java.io.ObjectInputStream;  
  8. import java.io.ObjectOutputStream;  
  9.   
  10. import model.Person;  
  11.   
  12. public class FileHelper {  
  13.     private String fileName;  
  14.       
  15.     public FileHelper(){  
  16.           
  17.     }  
  18.       
  19.     public FileHelper(String fileName){  
  20.         this.fileName=fileName;  
  21.     }  
  22.       
  23.     /* 
  24.      * 将person对象保存到文件中 
  25.      * params: 
  26.      *  p:person类对象 
  27.      */  
  28.     public void saveObjToFile(Person p){  
  29.         try {  
  30.             //写对象流的对象   
  31.             ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(fileName));  
  32.               
  33.             oos.writeObject(p);                 //将Person对象p写入到oos中   
  34.               
  35.             oos.close();                        //关闭文件流   
  36.         } catch (FileNotFoundException e) {  
  37.             // TODO Auto-generated catch block   
  38.             e.printStackTrace();  
  39.         } catch (IOException e) {  
  40.             // TODO Auto-generated catch block   
  41.             e.printStackTrace();  
  42.         }   
  43.     }  
  44.       
  45.     /* 
  46.      * 从文件中读出对象,并且返回Person对象 
  47.      */  
  48.     public Person getObjFromFile(){  
  49.         try {  
  50.             ObjectInputStream ois=new ObjectInputStream(new FileInputStream(fileName));  
  51.               
  52.             Person person=(Person)ois.readObject();              //读出对象   
  53.               
  54.             return person;                                       //返回对象   
  55.         } catch (FileNotFoundException e) {  
  56.             // TODO Auto-generated catch block   
  57.             e.printStackTrace();  
  58.         } catch (IOException e) {  
  59.             // TODO Auto-generated catch block   
  60.             e.printStackTrace();  
  61.         } catch (ClassNotFoundException e) {  
  62.             // TODO Auto-generated catch block   
  63.             e.printStackTrace();  
  64.         }  
  65.           
  66.         return null;  
  67.     }  
  68. }  
package saveobject;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import model.Person;

public class FileHelper {
	private String fileName;
	
	public FileHelper(){
		
	}
	
	public FileHelper(String fileName){
		this.fileName=fileName;
	}
	
	/*
	 * 将person对象保存到文件中
	 * params:
	 * 	p:person类对象
	 */
	public void saveObjToFile(Person p){
		try {
			//写对象流的对象
			ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(fileName));
			
			oos.writeObject(p);                 //将Person对象p写入到oos中
			
			oos.close();                        //关闭文件流
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
	
	/*
	 * 从文件中读出对象,并且返回Person对象
	 */
	public Person getObjFromFile(){
		try {
			ObjectInputStream ois=new ObjectInputStream(new FileInputStream(fileName));
			
			Person person=(Person)ois.readObject();              //读出对象
			
			return person;                                       //返回对象
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}
}

2.保存对象到数据库并恢复

对象序列化之后得到的二进制流,所以要想保存序列化之后的对象,则必须用blob字段来保存。mysql中blob字段是用来存储二进制数据的。可以直接用PreparedStatement.setObject()方法来保存对象到数据库中。

而要将对象恢复,则首先需要读出二进制数据,读出的方法是用ResultSet.getBlob()方法,然后用Blob对象的getBinaryStream()方法来获得二进制流对象,然后将该二进制流对象作为参数构造带缓冲区的流对象BufferedStream,然后用byte[]数组从BufferedInputStream流中读取二进制数据,然后用该byte数组来构造ByteArrayInputStream,然后用ByteArrayInputStream来构造ObjectInputStream,最后直接用ObjectInputStream对象的readObject方法读出对象数据,并强制性转化为原始的对象数据。

实现代码如下所示:

  1. package saveobject;  
  2.   
  3. import java.io.BufferedInputStream;  
  4. import java.io.ByteArrayInputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.io.ObjectInputStream;  
  8. import java.sql.Blob;  
  9. import java.sql.Connection;  
  10. import java.sql.DriverManager;  
  11. import java.sql.PreparedStatement;  
  12. import java.sql.ResultSet;  
  13. import java.sql.SQLException;  
  14. import java.util.ArrayList;  
  15. import java.util.List;  
  16.   
  17. import model.Person;  
  18.   
  19. public class DBHelper {  
  20.     private static Connection conn;                                      //连接   
  21.     private PreparedStatement pres;                                      //PreparedStatement对象   
  22.       
  23.     static{  
  24.         try {  
  25.             Class.forName("com.mysql.jdbc.Driver");              //加载驱动   
  26.             System.out.println("数据库加载成功!!!");  
  27.             String url="jdbc:mysql://localhost:3306/testdb";  
  28.             String user="root";  
  29.             String password="20130436";  
  30.               
  31.             conn=DriverManager.getConnection(url,user,password); //建立连接   
  32.             System.out.println("数据库连接成功!!!");  
  33.         } catch (ClassNotFoundException | SQLException e) {  
  34.             // TODO Auto-generated catch block   
  35.             e.printStackTrace();  
  36.         }  
  37.     }  
  38.       
  39.     /* 
  40.      * 向数据库中的表testobj中插入多个Person对象 
  41.      * params: 
  42.      *  persons:Person对象list 
  43.      */  
  44.     public void savePerson(List<Person> persons){  
  45.         String sql="insert into objtest(obj) values(?)";  
  46.           
  47.         try {  
  48.             pres=conn.prepareStatement(sql);  
  49.             for(int i=0;i<persons.size();i++){  
  50.                 pres.setObject(1, persons.get(i));  
  51.                    
  52.                 pres.addBatch();                                   //实现批量插入   
  53.             }  
  54.               
  55.             pres.executeBatch();                                      //批量插入到数据库中   
  56.               
  57.             if(pres!=null)  
  58.                 pres.close();  
  59.               
  60.         } catch (SQLException e) {  
  61.             // TODO Auto-generated catch block   
  62.             e.printStackTrace();  
  63.         }  
  64.     }  
  65.       
  66.     /* 
  67.      * 从数据库中读出存入的对象 
  68.      * return: 
  69.      *  list:Person对象列表 
  70.      */  
  71.     public List<Person> getPerson(){  
  72.         List<Person> list=new ArrayList<Person>();  
  73.         String sql="select obj from objtest";  
  74.           
  75.         try {  
  76.             pres=conn.prepareStatement(sql);  
  77.               
  78.             ResultSet res=pres.executeQuery();  
  79.             while(res.next()){  
  80.                 Blob inBlob=res.getBlob(1);                             //获取blob对象   
  81.                   
  82.                 InputStream is=inBlob.getBinaryStream();                //获取二进制流对象   
  83.                 BufferedInputStream bis=new BufferedInputStream(is);    //带缓冲区的流对象   
  84.                   
  85.                 byte[] buff=new byte[(int) inBlob.length()];  
  86.                 while(-1!=(bis.read(buff, 0, buff.length))){            //一次性全部读到buff中   
  87.                     ObjectInputStream in=new ObjectInputStream(new ByteArrayInputStream(buff));  
  88.                     Person p=(Person)in.readObject();                   //读出对象   
  89.                       
  90.                     list.add(p);  
  91.                 }  
  92.                   
  93.             }  
  94.         } catch (SQLException | IOException | ClassNotFoundException e) {  
  95.             // TODO Auto-generated catch block   
  96.             e.printStackTrace();  
  97.         }  
  98.           
  99.         return list;  
  100.     }  
  101. }  
package saveobject;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import model.Person;

public class DBHelper {
	private static Connection conn;                                      //连接
	private PreparedStatement pres;                                      //PreparedStatement对象
	
	static{
		try {
			Class.forName("com.mysql.jdbc.Driver");              //加载驱动
			System.out.println("数据库加载成功!!!");
			String url="jdbc:mysql://localhost:3306/testdb";
			String user="root";
			String password="20130436";
			
			conn=DriverManager.getConnection(url,user,password); //建立连接
			System.out.println("数据库连接成功!!!");
		} catch (ClassNotFoundException | SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/*
	 * 向数据库中的表testobj中插入多个Person对象
	 * params:
	 * 	persons:Person对象list
	 */
	public void savePerson(List<Person> persons){
		String sql="insert into objtest(obj) values(?)";
		
		try {
			pres=conn.prepareStatement(sql);
			for(int i=0;i<persons.size();i++){
				pres.setObject(1, persons.get(i));
				 
				pres.addBatch();                                   //实现批量插入
			}
			
			pres.executeBatch();                                      //批量插入到数据库中
			
			if(pres!=null)
				pres.close();
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/*
	 * 从数据库中读出存入的对象
	 * return:
	 * 	list:Person对象列表
	 */
	public List<Person> getPerson(){
		List<Person> list=new ArrayList<Person>();
		String sql="select obj from objtest";
		
		try {
			pres=conn.prepareStatement(sql);
			
			ResultSet res=pres.executeQuery();
			while(res.next()){
				Blob inBlob=res.getBlob(1);                             //获取blob对象
				
				InputStream is=inBlob.getBinaryStream();                //获取二进制流对象
				BufferedInputStream bis=new BufferedInputStream(is);    //带缓冲区的流对象
				
				byte[] buff=new byte[(int) inBlob.length()];
				while(-1!=(bis.read(buff, 0, buff.length))){            //一次性全部读到buff中
					ObjectInputStream in=new ObjectInputStream(new ByteArrayInputStream(buff));
					Person p=(Person)in.readObject();                   //读出对象
					
					list.add(p);
				}
				
			}
		} catch (SQLException | IOException | ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return list;
	}
}


测试用的main方法:

  1. package controller;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Date;  
  5. import java.util.List;  
  6.   
  7. import model.Person;  
  8. import saveobject.DBHelper;  
  9. import saveobject.FileHelper;  
  10.   
  11. public class MainApp {  
  12.     public static void main(String[] args){  
  13.         FileHelper fh=new FileHelper("E:\\obj.txt");  
  14.           
  15.         Person p=new Person();  
  16.         p.setName("张斌");  
  17.         p.setYear(24);  
  18.         p.setCity("威海");  
  19.         p.setBirth(new Date(95,2,16));  
  20.         fh.saveObjToFile(p);                               //存入person对象   
  21.           
  22.         Person person=fh.getObjFromFile();                 //取出person对象   
  23.         System.out.println(person.toString());  
  24.           
  25.         Person p1=new Person();  
  26.         p1.setName("张斌");  
  27.         p1.setYear(24);;  
  28.         p1.setCity("江西");  
  29.         p1.setBirth(new Date(94,1,2));  
  30.           
  31.           
  32.         Person p2=new Person();  
  33.         p2.setName("福国");  
  34.         p2.setYear(30);  
  35.         p2.setCity("吉林");  
  36.         p2.setBirth(new Date(95,4,23));  
  37.           
  38.         Person p3=new Person();  
  39.         p3.setName("羿赫");  
  40.         p3.setYear(20);  
  41.         p3.setCity("海南");  
  42.         p3.setBirth(new Date(93,9,29));  
  43.           
  44.         DBHelper db=new DBHelper();  
  45.         List<Person> slist=new ArrayList<Person>();  
  46.         slist.add(p1);  
  47.         slist.add(p2);  
  48.         slist.add(p3);  
  49.           
  50.         //db.savePerson(slist);   
  51.           
  52.         List<Person> glist=db.getPerson();  
  53.           
  54.         for(int i=0;i<glist.size();i++){  
  55.             System.out.println(glist.get(i).toString());  
  56.         }  
  57.     }  
  58. }  
package controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import model.Person;
import saveobject.DBHelper;
import saveobject.FileHelper;

public class MainApp {
	public static void main(String[] args){
		FileHelper fh=new FileHelper("E:\\obj.txt");
		
		Person p=new Person();
		p.setName("张斌");
		p.setYear(24);
		p.setCity("威海");
		p.setBirth(new Date(95,2,16));
		fh.saveObjToFile(p);                               //存入person对象
		
		Person person=fh.getObjFromFile();                 //取出person对象
		System.out.println(person.toString());
		
		Person p1=new Person();
		p1.setName("张斌");
		p1.setYear(24);;
		p1.setCity("江西");
		p1.setBirth(new Date(94,1,2));
		
		
		Person p2=new Person();
		p2.setName("福国");
		p2.setYear(30);
		p2.setCity("吉林");
		p2.setBirth(new Date(95,4,23));
		
		Person p3=new Person();
		p3.setName("羿赫");
		p3.setYear(20);
		p3.setCity("海南");
		p3.setBirth(new Date(93,9,29));
		
		DBHelper db=new DBHelper();
		List<Person> slist=new ArrayList<Person>();
		slist.add(p1);
		slist.add(p2);
		slist.add(p3);
		
		//db.savePerson(slist);
		
		List<Person> glist=db.getPerson();
		
		for(int i=0;i<glist.size();i++){
			System.out.println(glist.get(i).toString());
		}
	}
}

程序结果截图:

数据库截图:

如果是数据完全可以使用JSON方式。毕竟redis直接set、get使用起
来门槛低很多。redis是没有提供专用的设置对象方法,需要自己进行改写。如果是担心JSON转对象会消耗资源的情况,这个问题需要考量几个地方,第一
点:就是使用的JSON转换lib是否就会存在性能问题。第二点:就是数据的数据量级别,如果是存储百万级的大数据对象,建议采用存储序列化对象方式。如
果是少量的数据级对象,或者是数据对象字段不多,还是建议采用JSON转换成String方式。毕竟redis对存储字符类型这部分优化的非常好。具体采
用的方式与方法,还要看你所使用的场景。

Redis不支持直接将Java对象存储到数据库中,所以需要将java对象进行序列化得到字节数组,然后将字节数组存入到redis中,需要数据的时候就从redis数据库中取出字节数组,再经过反序列化将自己数组转换成对象使用(jdk序列化性能比谷歌公司的Protobuf序列化性能要差一些,而且序列化后的字节长度要也会长一些,所以推荐使用Protobuf,Protobuf如何进行序列化请看我的另一篇帖子)
实体类
User.java

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. import java.io.Serializable;  
  2. public class User implements Serializable{  
  3. private static final long serialVersionUID = 2724888087391664167L;  
  4. private String id;  
  5. private String username;  
  6. private String password;  
  7. public User() {  
  8. }  
  9. public User(String id, String username, String password) {  
  10. this.id = id;  
  11. this.username = username;  
  12. this.password = password;  
  13. }  
  14. public String getId() {  
  15. return id;  
  16. }  
  17. public void setId(String id) {  
  18. this.id = id;  
  19. }  
  20. public String getUsername() {  
  21. return username;  
  22. }  
  23. public void setUsername(String username) {  
  24. this.username = username;  
  25. }  
  26. public String getPassword() {  
  27. return password;  
  28. }  
  29. public void setPassword(String password) {  
  30. this.password = password;  
  31. }  
  32. public static long getSerialversionuid() {  
  33. return serialVersionUID;  
  34. }  
  35. @Override  
  36. public String toString() {  
  37. return "User [id=" + id + ", username=" + username + ", password="  
  38. + password + "]";  
  39. }  
  40. }  
序列化反序列化工具类
SerializeUtils.java
[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  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. public class SerializeUtils {  
  7. public static byte[] serialize(Object obj){  
  8. byte[] bytes = null;  
  9. try {  
  10. ByteArrayOutputStream baos=new ByteArrayOutputStream();;  
  11. ObjectOutputStream oos=new ObjectOutputStream(baos);  
  12. oos.writeObject(obj);  
  13. bytes=baos.toByteArray();  
  14. baos.close();  
  15. oos.close();  
  16. catch (IOException e) {  
  17. e.printStackTrace();  
  18. }  
  19. return bytes;  
  20. }  
  21. public static Object deSerialize(byte[] bytes){  
  22. Object obj=null;  
  23. try {  
  24. ByteArrayInputStream bais=new ByteArrayInputStream(bytes);  
  25. ObjectInputStream ois=new ObjectInputStream(bais);  
  26. obj=ois.readObject();  
  27. catch (Exception e) {  
  28. e.printStackTrace();  
  29. }  
  30. return obj;  
  31. }  
  32. }  
测试类RedisTest.java
[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. import java.util.HashMap;  
  2. import java.util.List;  
  3. import java.util.Map;  
  4. import java.util.Set;  
  5. import org.junit.Test;  
  6. import redis.clients.jedis.Jedis;  
  7. public class RedisTest{  
  8. private static Jedis jedis;  
  9. static{  
  10. //访问本地redis  
  11. jedis = new Jedis("127.0.0.1",6379);  
  12. }  
  13. @Test  
  14. public void serialize(){  
  15. User user=new User("1000""宝宝""xioabao");  
  16. jedis.set(user.getId().getBytes(), SerializeUtils.serialize(user));  
  17. byte[] bytes=jedis.get(user.getId().getBytes());  
  18. System.out.println((User)SerializeUtils.deSerialize(bytes));  
  19. }  
  20. }  

猜你喜欢

转载自jieke-zj.iteye.com/blog/2397864