繁体   English   中英

我可以使用 map 一个字段到数据库中的两列使用 Hibernate 吗?

[英]Can I map one single field to two columns in the database using Hibernate?

考虑以下 Java Hibernate 实体示例(代码片段):

...

@Column
@Converter(...)
private String columnOne;

public String getcolumnOne() {
    return columnOne;
}

public setColumnOne(String columnOne) {
    this.columnOne = columnOne;
}

...

这将生成一个COLUMN_ONE是数据库。

我如何/应该在从同一字段columnOne字段生成的数据库表中生成第二列COLUMN_TWO 这第二列在使用该实体的 Java 代码中并不重要,因此我的实体不应将此第二列导出给该实体的用户。 COLUMN_TWO将用于数据库本身(用于某些索引)和其他应用程序。

免责声明:我没有尝试过,但我相信 Hibernate 可以访问私有方法,因为它可以访问私有字段。

对于此示例,假设您有一个LocalDateTime类型的属性,如 class 的用户所见,但您希望将值存储为 ISO-8601 格式的字符串 ( VARCHAR ),其中日期在一列中,时间在另一列。

所以你有正常的private字段和正常的public getter/setter 方法。 您也没有将@Column放在上面,而是使用@Transient使 JPA 忽略该属性。

然后,您创建两个派生的 getter/setter 方法对,将它们设为private ,以便 class 的用户无法看到它们,然后用@Column注释这两对方法,以使 JPA 在数据库中持久化时使用它们。

private LocalDateTime dateTime;

@Transient // Do not persist in database
public LocalDateTime getDateTime() {
    return this.dateTime;
}

public void setDateTime(LocalDateTime dateTime) {
    this.dateTime = dateTime;
}

@Column(name = "FOO_DATE", nullable = true, length = 10)
private String getDate() {
    if (this.dateTime == null)
        return null;
    return this.dateTime.toLocalDate().toString();
}

private void setDate(String date) {
    if (date == null) {
        this.dateTime = null;
    } else {
        LocalDate date = LocalDate.parse(date);
        LocalTime time = (this.dateTime == null ? LocalTime.MIDNIGHT
                          : this.dateTime.toLocalTime());
        this.dateTime = LocalDateTime.of(date, time);
    }
}

@Column(name = "FOO_TIME", nullable = true, length = 12)
private String getTime() {
    if (this.dateTime == null)
        return null;
    return this.dateTime.toLocalTime()
               .format(DateTimeFormatter.ofPattern("HH:mm:ss.SSS"));
}

private void setTime(String time) {
    if (time == null) {
        this.dateTime = null;
    } else {
        LocalTime time = LocalTime.parse(time);
        LocalDate date = (this.dateTime == null ? LocalDate.ofEpochDay(0)
                          : this.dateTime.toLocalDate());
        this.dateTime = LocalDateTime.of(date, time);
    }
}

您必须决定是否希望您的数据库设计由您的实体设计驱动,或者您是否希望将两者分离。

如果您不需要实体中的列,那么就不要 map 它。 如果您使用这种方法的“问题”是,hbm2ddl 不会生成您必须确定实体 model 是否真的应该是数据库设计的驱动程序的列。 您可以(并且 IMO 应该)使用像 Liquibase 或 Flyway 这样的工具来进行数据库架构迁移。 这样,您可以在数据库中有列,同时在实体中没有 map。

我知道这对于你的小用例来说可能太多了,但我建议你最终这样做,因为你会在某些时候需要它。 无论如何,您也可以将 map 作为私有字段而不暴露该字段。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM