无法在列中插入NULL

时间:2011-08-31 21:56:37

标签: java oracle hibernate spring

我试图让Hibernate懒得加载一些clobs。装载部分工作得很好。问题是当我尝试创建一个新的。我从Blob lazy loading

的建议开始

这是我的映射(请注意,表格结构非常糟糕,此表上有多个clob - 此示例已从我的真实模型中简化...)。

@Entity @Table("TABLE_1")
public class BadDBDesign {
  @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column("table_id")
  private long key;

  @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  @JoinColumn(name = "table_id", referencedColumnName = "table_id", 
              insertable = true, updatable = false)
  private BlobWrapperA;

  @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  @JoinColumn(name = "table_id", referencedColumnName = "table_id",
              insertable = true, updatable = false)
  private BlobWrapperB;
}

@Entity @Table(name = "TABLE_1")
public class BlobWrapperA {
  @Lob
  @Column(name = "col_A", nullable = false)
  @Type(type = "org.springframework.orm.hibernate3.support.BlobByteArrayType")
  private byte[] blobColA;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "table_id")
  private long Key;
}

@Entity @Table(name = "TABLE_1")
public class BlobWrapperB {
  @Lob
  @Column(name = "col_B", nullable = false)
  @Type(type = "org.springframework.orm.hibernate3.support.BlobByteArrayType")
  private byte[] blobColB;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "table_id")
  private long Key;
}

应用程序启动很好,能够在不加载clobs的情况下检索数据(能够通过延迟加载在需要时检索它们),但是当我尝试创建新的时,我会收到以下stacktrace:

Hibernate: 
  insert 
  into
    TABLE_1
    (key, col_A, col_B) 
values
    (?, ?, ?)
2011-08-31 17:35:09,089 [http-8080-1] DEBUG org.springframework.jdbc.support.lob.DefaultLobHandler IP134.167.141.34 CV#f2a597b2-a185-4e89 P#71252 - Set bytes for BLOB with length 7136
2011-08-31 17:35:16,441 [http-8080-1] DEBUG org.springframework.jdbc.support.lob.DefaultLobHandler IP134.167.141.34 CV#f2a597b2-a185-4e89 P#71252 - Set bytes for BLOB with length 10946
Aug 31, 2011 5:35:50 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet online threw exception java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("SCHEMA"."TABLE_1"."COL_A")

at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:440)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:837)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:445)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:191)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:523)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1010)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1315)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3576)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3657)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1350)
at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)

注意重要的部分,我们在生成的SQL的Hibernate insert语句之后立即看到clobs的长度。

编辑:今天早上看完这个后,我意识到问题是由于其中一个Blob必须与@JoinColumn映射(insertable = false,updatable = false),否则Hibernate不会启动。当然,它试图将Null插入此列。所以新的问题就变成了,你可以在一张桌子上懒散地 MULTIPLE clobs(使用相同的密钥)。我猜测没有桌面重新设计,除非Oracle修复驱动程序,否则我几乎不走运。

3 个答案:

答案 0 :(得分:3)

尽管它让我想要呕吐,但我们需要在不修改数据库的情况下获得此功能。

因此,我将常见的部分抽取到类似的抽象类中:

@MappedSuperclass @Table("TABLE_1")
public class BadDBDesign {
  @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column("table_id")
  private long key;

  @Column("small_value")
  private String smallVarChar2Field;
}

问题是我必须为每个blob扩展这个类:(因此我们的扩展类就像:

public class BlobA extends BadDBDesign {
  @Lob @Column("col_a")
  @Type(type ="org.springframework.orm.hibernate3.support.BlobByteArrayType")
  private byte[] blobColA;
}

public class BlobB extends BadDBDesign {
  @Lob @Column("col_b")
  @Type(type ="org.springframework.orm.hibernate3.support.BlobByteArrayType")
  private byte[] blobColB;
}

幸运的是,我们没有任何位置,我们在任何给定的页面上都有多个clob。这仍然是维护的噩梦,但是在更有效地完成负载方面是可接受的权衡(暂时)。我为这些创建了DAO,项目之前没有;希望这将推动团队向正确的抽象层迈进,我们可以在未来的版本中完全删除这些浪费的POJO。

答案 1 :(得分:0)

在您的BlobWrapperA类中,您在该列上设置了“nullable = false”。或者该列对数据库中的表本身具有空约束。

答案 2 :(得分:0)

当涉及LOB类型时,Oracle和Hibernate互相讨厌,这源于Oracle驱动程序是垃圾的事实。我相信我之前遇到过这种情况,你应该尝试设置以下系统属性:

hibernate.jdbc.use_streams_for_binary=true
hibernate.jdbc.batch_size=0