java - Hibernate/JPA -> 可空值和对象?

标签 java hibernate orm jpa nullable

我的基本问题是:如何强制 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="&quot;test&quot;"/>
    <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    |            |
+--------+--------------+------+-----+---------+------------+

这不是我想要的。如你所见

  1. float 不可为空,
  2. “url”类型变成了 blob 而不是 varchar 并且
  3. 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[], and Character[]); 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/

相关文章:

java - IntelliJ IDEA "cannot access org.hibernate.query.QueryProducer"错误,但项目编译并运行正常

python - SQLAlchemy ORM : proxy attribute pointing to the first element of a relation?

java - 格式化骰子滚动输出 Java

java - 您可以只使用 AtomicInteger 来创建 ReadWriteLock 锁吗?

java - Artifact 丢失 : org. hibernate :hibernate-entitymanager:jar:3. 3.2.ga

database - 目前持久性的最佳实践是什么?

database - 关系数据库管理系统与对象数据库

java - 实例化对象用于显示另一个类中存储的信息

hibernate - 数据库ID递增一个以上

java - PostgreSQL 抛出 "Connection has been abandoned"-> "An I/O error occurred while sending to the backend"