我的基本问题是:如何强制 Hibernate 使 float 可以为 NULL,并分别为 float 、日期时间和 blob 接受 NULL?我的意思是 NULL,而不是 (float) 0.0。
更糟糕的是,当我尝试存储一个对象,其中所需的 NULLable 字段实际上是 NULL 并使用实体管理器时,我得到了属性错误,即使在 db 表中,这些属性也被 Hibernate 标记为 NULLable。
这是我一直在尝试但没有成功的方法:
考虑这个表:
+--------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| number | float | YES | | NULL | |
| url | varchar(3) | YES | | NULL | |
| mydate | date | YES | | NULL | |
+--------+--------------+------+-----+---------+----------------+
由这些语句创建:
DROP SCHEMA IF EXISTS `mydb` ;
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
USE `mydb` ;
DROP TABLE IF EXISTS `mydb`.`test` ;
CREATE TABLE IF NOT EXISTS `mydb`.`test` (
`id` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(255) NOT NULL ,
`number` FLOAT NULL,
`url` VARCHAR(3) NULL ,
`mydate` DATE NULL ,
PRIMARY KEY (`id`) ,
UNIQUE INDEX `id_UNIQUE` (`id` ASC) )
ENGINE = InnoDB;
如果我执行以下插入:
INSERT INTO `mydb`.`test` (`name`) VALUES ('MyName');
SELECT * FROM `mydb`.`test`;
我得到以下结果:
+----+--------+--------+------+--------+
| id | name | number | url | mydate |
+----+--------+--------+------+--------+
| 1 | MyName | NULL | NULL | NULL |
+----+--------+--------+------+--------+
1 row in set (0.00 sec)
这正是我想要的。
使用 Hibernate 3.5/JPA2,我尝试像这样做我的 ORM:
博:
public class BodyStat extends BusinessObject {
@Id
private int id;
private String name;
@Column(nullable = true)
private float number;
@Column(nullable = true)
private URL url;
@Column(nullable = true)
private Date myDate;
... C'Tor / setters / getters / eof
我的 orm.xml 中的实体如下所示:
<entity class="test">
<table name=""test""/>
<attributes>
<id name="id">
<generated-value strategy="TABLE"/>
</id>
<basic name="name"/>
<basic name="number" optional="true"/>
<basic name="url" optional="true"/>
<basic name="myDate" optional="true"/>
</attributes>
</entity>
现在 Hibernate 生成的表如下所示:
+--------+--------------+------+-----+---------+------------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+------------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(255) | NO | | NULL | |
| number | float | NO | | NULL | |
| url | tinyblob | YES | | NULL | |
| mydate | date | YES | | NULL | |
+--------+--------------+------+-----+---------+------------+
这不是我想要的。如你所见
- float 不可为空,
- “url”类型变成了 blob 而不是 varchar 并且
- mydate 为“日期”而不是“日期时间”
最佳答案
float is not nullable,
这个很奇怪。 nullable
仅用作表创建的列属性,并且无论映射的属性是否为基元都应该完成它的工作。至少你的代码适用于 Derby,我为生成的表获得了一个可为空的列。但显然,如果您希望能够“传递”null
值,则在对象级别使用包装器(即 Float
)是有意义的。
the type "url" turned out to as a blob rather than a varchar and
来自 JPA 1.0 规范:
2.1.1 Persistent Fields and Properties
...
The persistent fields or properties of an entity may be of the following types: Java primitive types;
java.lang.String
; other Java serializable types (including wrappers of the primitive types,java.math.BigInteger
,java.math.BigDecimal
,java.util.Date
,java.util.Calendar
,java.sql.Date
,java.sql.Time
,java.sql.Timestamp
, user-defined serializable types,byte[]
,Byte[]
,char[]
, andCharacter[]
); enums; entity types and/or collections of entity types; and embeddable classes (see section 2.1.5).
java.net.URL
是可序列化的,仅此而已(从 JPA 的角度来看),因此它被视为可序列化(并存储在 BLOB 中)。
如果您确实希望将其存储为 String
,请使用自定义 UserType
(特定于 Hibernate)或使用 String
holder并提供 getter/setter 进行转换(并将 getter 标记为 Transient)。像这样:
private String urlAsString;
@Transient
public URL getUrl() throws MalformedURLException {
return new URL(this.urlAsString);
}
public void setUrl(URL url) {
this.urlAsString = url.toString();
}
@Column(nullable = true)
protected String getUrlAsString() {
return urlAsString;
}
protected void setUrlAsString(String urlAsString) {
this.urlAsString = urlAsString;
}
mydate as "date" rather than "datetime"
如果您还想存储日期的时间部分,请使用@Temporal
注释将其映射为时间戳:
@Column(nullable = true)
@Temporal(TemporalType.TIMESTAMP)
private Date myDate;
PS:顺便问一下,为什么要同时提供注释和 orm.xml
?你知道它们在某种程度上是等价的吗?如果你可以使用注释,就使用它们,不需要那个 orm.xml
。
关于java - Hibernate/JPA -> 可空值和对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3225103/