SQLException: Incorrect string value
一、场景
业务上某些场景需要将对象存入数据库中,处理方式为:将对象转为字节数组存储,读取时再将字节数组转为对象;
模拟的表结构如下:
create table resource(
	fid int primary key not null auto_increment,
	fname varchar(255),
	fbytes longtext
) charset=utf8;
以User对象为例:
public class User implements Serializable{
	private static final long serialVersionUID = 3125265779564966137L;
	
	private String name;
	private int age;
	public User(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return String.format("User(%s, %s)", this.name, this.age);
	}
}
存储User对象:
User user = new User("albert", 30);
//将User对象转为字节数组
byte[] bytes = null;
try(ByteArrayOutputStream baos = new ByteArrayOutputStream()){
	try(ObjectOutputStream oos = new ObjectOutputStream(baos)){
		oos.writeObject(user);
		bytes = baos.toByteArray();
	}
}
//将数据存入数据库中
try(Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", username, password)){
	try(PreparedStatement statement = connection.prepareStatement("insert into resource(fname, fbytes) values(?,?);")){
		statement.setString(1, "A-001");
		statement.setBinaryStream(2, new ByteArrayInputStream(bytes), bytes.length);
		statement.execute();
	}
}
查询:
//从数据库中查询User对象数据
......
//将字节数组转为User对象
Object deserializedObject = null;
try(ByteArrayInputStream bais = new ByteArrayInputStream(bytes)){
	try(ObjectInputStream ois = new ObjectInputStream(bais)){
		deserializedObject = ois.readObject();
	}
}
System.out.println(deserializedObject);
在插入对象字节数组时报错java.sql.SQLException: Incorrect string value: '\xAC\xED\x00\x05sr...' for column 'fbytes' at row 1:
Exception in thread "main" java.sql.SQLException: Incorrect string value: '\xAC\xED\x00\x05sr...' for column 'fbytes' at row 1
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3491)
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3423)
	at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1936)
	at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2060)
	at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2542)
	at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1734)
	at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:995)
	at com.mysql.CharsetBinaryTest.main(CharsetBinaryTest.java:31)
二、解决方式
修改表字段类型,fbytes字段应该使用longblob类型:
ALTER TABLE resource MODIFY fbytes longblob;