Java中要实现将对象保存起来持久化,需要让对象实现Serializable接口,这样就能将java对象用二进制流保存并恢复。下面我将以保存到文件和保存到mysql来进行解析。先给出序列化类的定义:
- 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();
- }
- }
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.保存对象到文件并恢复
要保存到文件首先必须得获得文件输入流,然后将文件输入流作为参数,构造对象输入流,然后就能直接将对象输入到文件中。而要将对象恢复,则需要先获得文件输出流,然后将文件输出流作为参数,构造对象输出流,就能够得到对象,然后再强制性转换为原始对象即可,实现代码如下:
- 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;
- }
- }
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方法读出对象数据,并强制性转化为原始的对象数据。
实现代码如下所示:
- 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;
- }
- }
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方法:
- 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());
- }
- }
- }
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
序列化反序列化工具类
SerializeUtils.java
测试类RedisTest.java
相关推荐
对象关系映射,并持久化到数据库的开源组件,是对JDBC 的封装,主要负责java 对象的持久化.。 对象序列化适应临时的少量的对象备份。 对象持久化和关系型数据库联合在一起,适应大量的对象持久存储
Java中的序列化(serialization)机制能够将一个实例对象的状态信息写入到一个字节流中,使其可以通过socket进行传输、或者持久化存储到数据库或文件系统中;然后在需要的时候,可以根据字节流中的信息来重构一个...
数据库系统原理实验 数据库管理系统 javase java 大学数据库实验 主要利用JAVA序列化和反序列化 注解挺全的,DBMS, 文件存储表、库,根据sql语句实现建表,建库 可以建立索引(B+树) 可以做笛卡尔积(hash) 自然...
第2章 Java对象持久化技术概述 2.1 直接通过JDBC API来持久化实体域对象 2.2 ORM简介 2.2.1 对象-关系映射的概念 2.2.2 ORM中间件的基本使用方法 2.2.3 常用的ORM中间件 2.3 实体域对象的其他持久化模式...
Java 序列化是指把 Java 对象转换为字节序列的过程,便于保存在内存、文件、数据库中,ObjectOutputStream类的 writeObject() 方法可以实现序列化。反序列化是指把字节序列恢复为 Java 对象的过程,...
序列化的应用场景:将对象存储在文件或数据库中,利用套接字在网络上进行对象传输,RMI(远程方法调用)传输对象。 序列化的实现一般是通过实现Serializable接口,并且会有一个serialVersionUID,这个ID叫做序列化...
定义对象及其关系后,您可以将它们序列化为java类,该类将自动序列化和反序列化为MySQL。 此输出可用于加快将数据持久存储在数据库中的程序的开发。 该程序有一天可能会扩展到涵盖其他语言和数据库。
第1部分 介绍数据库、SQL和JDBC 第1章 关系型数据库 1.1 理解关系型数据库管理系统 1.1.1 关系模型 1.1.2 Codd法则 1.1.3 表、行、列和关键字 1.1.4 主键 1.1.5 外键 1.1.6 关系 1.1.7 视图 1.1.6 范式...
Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。 java.net 为实现网络应用程序提供类。 java....
第2章 Java对象持久化技术概述 2.1 直接通过JDBC API来持久化实体域对象 2.2 ORM简介 2.2.1 对象-关系映射的概念 2.2.2 ORM中间件的基本使用方法 2.2.3 常用的ORM中间件 2.3 实体域对象的其他持久化模式...
第2章 Java对象持久化技术概述 2.1 直接通过JDBC API来持久化实体域对象 2.2 ORM简介 2.2.1 对象-关系映射的概念 2.2.2 ORM中间件的基本使用方法 2.2.3 常用的ORM中间件 2.3 实体域对象的其他持久化模式...
第2章 Java对象持久化技术概述 2.1 直接通过JDBC API来持久化实体域对象 2.2 ORM简介 2.2.1 对象-关系映射的概念 2.2.2 ORM中间件的基本使用方法 2.2.3 常用的ORM中间件 2.3 实体域对象的其他持久化模式...
Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
序列化和反序列化对象(将不长用的对象暂时持久化到文件中为对象的序列化,反之用时再把对象恢复到内存为反序列化); 控制对象的序列化和反序列化; 读jar包的资源文件;用zip格式压缩 和解压文件;操作Excel文件;...