在 MySQL 中将 Java 对象存储为 BLOB:奇怪的错误

Posted

技术标签:

【中文标题】在 MySQL 中将 Java 对象存储为 BLOB:奇怪的错误【英文标题】:store Java Object as BLOB in MySQL: strange error 【发布时间】:2012-02-22 08:30:12 【问题描述】:

有个小问题希望有人能指教一下。

尝试序列化我自己创建的 Java 对象,该对象由其他 Java 对象组成(再次是我自己创建的)。当 jdbc 尝试运行将对象存储为 blob 的 PreparedStatement 时,它运行良好,直到我收到此错误。

我将 mysql 作为数据库运行,并检查了我试图存储在 blob 字段中的所有对象是否都定义为“实现可序列化”。我试图在 MySQL 和 MedBlob 中尝试普通的 BLOB 数据类型。我正在通过 Xampp 运行 MySQL 客户端版本:5.1.41。

代码如下:

LinkedList<Table> tt = t;
//Ignore these two variables
String tName = "";
int modelCode = 0;

for (int i = 0; i< tt.size();i++)
    tName = t.get(i).getTableName();
    modelCode = session.getCurrentModel();
    try 
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(baos);
      oos.writeObject(t.get(i));

      byte[] tableAsBytes = baos.toByteArray();
      fyProject.connectionController sg = new fyProject.connectionController(1);

      PreparedStatement pstmt =
         sg.prepareSQL
            ("INSERT INTO tableList (table) VALUES(?);");

      ByteArrayInputStream bais =
         new ByteArrayInputStream(tableAsBytes);

      pstmt.setBinaryStream(1,bais, (long) tableAsBytes.length);
      System.out.println(pstmt.toString());
      //pstmt.setString(2, tName);
      //pstmt.setInt(3, modelCode);

      pstmt.executeUpdate();
      sg.conn.commit();
      pstmt.close();
      conn.close();
    catch(Exception e) 
        e.printStackTrace();
    

错误堆栈如下:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'table) VALUES(_binary'¬í\0sr\0fyProject.TableÊl;EÞ›\0L\0
attributest\0Lja' at line 1
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
        at com.mysql.jdbc.Util.getInstance(Util.java:386)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1052)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2624)

        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2127)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2427)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2345)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2330)
        at fyProject.connectionController.insertTable(connectionController.java:368)
        at fyProject.connectionController.createTables(connectionController.java:292)
        at fyProject.Main.main(Main.java:40)

感谢您的帮助。

刘易斯

编辑:固定代码如下。

   public void insertTable() 
    LinkedList<Table> tt = t;
    //Ignore these two variables
    String tName = "";
    int modelCode = 0;

        for (int i = 0; i< tt.size();i++)
            tName = tt.get(i).getTableName();
            modelCode = session.getCurrentModel();
            try 
              ByteArrayOutputStream baos = new ByteArrayOutputStream();
              ObjectOutputStream oos = new ObjectOutputStream(baos);
              //Test a = new Test(1);
              oos.writeObject(tt.get(i));

              byte[] tableAsBytes = baos.toByteArray();
              fyProject.connectionController sg = new fyProject.connectionController(1);

              PreparedStatement pstmt =
                 sg.prepareSQL
                    ("INSERT INTO tableList (tableField) VALUES(?);");

              ByteArrayInputStream bais =
                 new ByteArrayInputStream(tableAsBytes);

              pstmt.setBinaryStream(1,bais, (long) tableAsBytes.length);
              System.out.println(pstmt.toString());
              //pstmt.setString(2, tName);
              //pstmt.setInt(3, modelCode);

              pstmt.executeUpdate();
              //sg.conn.commit();
              pstmt.close();
              conn.close();
            catch(Exception e) 
                e.printStackTrace();
            
        
    

【问题讨论】:

【参考方案1】:

TABLE 是 MySQL keyword。由于您将其用作列的名称,因此您需要像这样对名称进行转义:

INSERT INTO tableList (`table`) VALUES(?);

【讨论】:

谢谢五位!就像旁注一样,即使使用上述语句我也遇到了问题,即使使用单引号括起来,似乎表作为字段名称也不能在 MySQL 中使用。我将字段名称更改为“tableField”(不带单引号),效果很好。我会为再次遇到此问题的任何人发布我的新 Java 代码。 您实际上可以使用表作为列名,但您需要使用反引号 (`) 来转义查询中的表名和列名。单引号用于字符串文字。 真的吗?当我尝试 INSERT INTO tableList (table) VALUES(?);我得到了一个不同的错误,但是当我将字段名称更改为 tableField 然后 SQL 读取 INSERT INTO tableList (tableField) VALUES(?);我没有问题。奇怪的;无论哪种方式,感谢您的帮助,这一天我一直在摸索。

以上是关于在 MySQL 中将 Java 对象存储为 BLOB:奇怪的错误的主要内容,如果未能解决你的问题,请参考以下文章

在 PHP/MySQL 中将日期时间存储为 UTC

如何在 MySQL 中将 1/3 存储为小数

在 Hibernate 中将自定义对象属性存储为列

通过使用 MySQL 的 DataJpaTest 存储库测试,Hibernate 不会在 H2 DB 中将用户设置为自动增量

在 Neo4j 中将对象存储为属性

如何在 oracle 存储过程中将对象类型设置为 out?