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;