[英]Using Joda DateTime with Hibernate in H2 Database - SQLError
[英]Using Hibernate with H2 database and joda DateTime
我正在使用Hibernate与H2内存数据库。 根据我在persistence.xml文件中提供的bean信息自动创建数据库表。
H2将类型为org.joda.time.DateTime的名为“created”的字段映射到VARBINARY类型的列(255)
当我尝试使用created=DateTime.now()
的值created=DateTime.now()
来持久保存bean时,出现以下错误:
Caused by: org.h2.jdbc.JdbcSQLException: Value too long for column "CREATED BINARY(255)": "X'aced0005737200166f72672e6a6f64612e74696d652e4461746554696d65b83c78646a5bddf90200007872001f6f72672e6a6f64612e74696d652e62617365... (273)";
SQL statement:
insert into mytable (id, created) values (null, ?) [22001-168]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
知道为什么以及我能做些什么来解决它? 不幸的是我不能改变bean的定义,所以我必须继续使用joda DateTime。
谢谢!
PS这是我的persistence.xml
<persistence-unit name="my-test" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.model.MyTable</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<shared-cache-mode>ALL</shared-cache-mode>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/c:\UnitTest;INIT=CREATE SCHEMA IF NOT EXISTS UnitTest" />
<property name="javax.persistence.jdbc.user" value="SA" />
<property name="javax.persistence.jdbc.password" value="" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<property name="hibernate.show_sql" value = "true" />
<property name="hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.max_fetch_depth" value="4" />
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.EhCacheRegionFactory" />
</properties>
</persistence-unit>
并且表由Hibernate / H2自动生成:
MYTABLE
ID BIGINT(19) NOT NULL
CREATED VARBINARY(255)
这是我的豆子:
@Entity
@Table(name = "MyTable")
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public class MyTable implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
public Long getId() {
return id;
}
@SuppressWarnings("unused")
private void setId(Long id) {
this.id = id;
}
@Column(name = "created")
private DateTime created;
public DateTime getCreated() {
return created;
}
@SuppressWarnings("unused")
private void setCreated(DateTime created) {
this.created = created;
}
public MyTable() {
}
public MyTable(DateTime created) {
this.created = created;
}
@Override
public boolean equals(Object obj) {
...
}
@Override
public int hashCode() {
...
}
}
这里是您的问题的演示(和解释):
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(new DateTime());
oos.close();
System.out.println("Serialized size: " + bos.toByteArray().length); // output: 273
因此,当序列化为字节数组时, DateTime
-object需要273个字节。 由于列类型接受字节数组,但配置为仅接受最大255个字节,因此您将获得SQL异常。 如果要保留JodaTime和字节数组存储机制,只有一种方法可以解决问题:将列大小增加到至少273(需要编辑persistence.xml
)。
编辑:你有可能重新考虑存储机制吗? 列类型VARBINARY似乎不是最佳选择,因为它的大小(你甚至不能在这种类型的SQL中应用比较运算符)。 替代方案是VARCHAR(但仅限于ISO-8601表示法)或SQL-TIMESTAMP。 特别注意这个Joda-Hibernate支持 ,以便使用Type-annotations和更好的列类型。
你应该使用Joda-Time-Hibernate映射:
@Type(类型= “org.joda.time.contrib.hibernate.PersistentDateTime”)
您可以在MYTABLE.groovy域上映射CREATED列长度:
static mapping = {
CREATED column: "CREATED", sqlType: "VARBINARY", length:273 }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.