【问题标题】:How to set different types for getter, setter and database field with Hibernate?如何使用 Hibernate 为 getter、setter 和数据库字段设置不同的类型?
【发布时间】:2013-07-03 09:21:40
【问题描述】:

我在 H2 数据库中有一个时间戳字段,但我需要使用 Hibernate 4.3 从我的 bean 中获取 String 而不是 Date,所以我试图在我的 bean 中这样做:

import java.util.Date;

...

private Date msgDate;
@Column(name = "msgDate", columnDefinition="timestamp")
public String getMsgDate() {
    SimpleDateFormat df = new SimpleDateFormat("yyyy MM dd HH mm ss");
    return df.format(msgDate);
}

public void setMsgDate(Date msgDate) {
    this.msgDate = msgDate;
}

但我有下一个错误:

    ERROR: HHH000123: IllegalArgumentException in class: Messages, setter method of property: msgDate
июл 03, 2013 11:39:56 AM org.hibernate.property.BasicPropertyAccessor$BasicSetter set
ERROR: HHH000091: Expected type: java.util.Date, actual value: java.lang.String
июл 03, 2013 11:39:56 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [MessageList] in context with path [/messenger] threw exception
org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of com.epam.epamlab.messenger.beans.Messages.msgDate
    at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:119)
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:711)
    at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:371)
    at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:4519)
    at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:188)
    at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:144)
    at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1102)
    at org.hibernate.loader.Loader.processResultSet(Loader.java:959)
    at org.hibernate.loader.Loader.doQuery(Loader.java:906)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:340)
    at org.hibernate.loader.Loader.doList(Loader.java:2523)
    at org.hibernate.loader.Loader.doList(Loader.java:2509)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2339)
    at org.hibernate.loader.Loader.list(Loader.java:2334)
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:491)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:369)
    at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:222)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1270)
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
    ...
Caused by: java.lang.IllegalArgumentException: argument type mismatch
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:65)
    ... 40 more

如果我从 getter 返回 Date,一切正常。为什么 Hibernate 等待 Date 类型返回,即使在注释中使用 columnDefinition 之后?我应该如何正确地做到这一点?

【问题讨论】:

    标签: java hibernate annotations


    【解决方案1】:

    保持 getter/setter 不变。 Hibernate 需要这些方法与字段的类型保持一致才能执行操作。没有什么能阻止您在类中定义自己的特殊 get 方法。

    private Date msgDate;
    @Column(name = "msgDate", columnDefinition="timestamp")
    public Date getMsgDate() {
       return this.msgDate;
    }
    
    public void setMsgDate(Date msgDate) {
        this.msgDate = msgDate;
    }
    
    public Date getMsgDateFormatted() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy MM dd HH mm ss");
        return df.format(msgDate);
    }
    

    【讨论】:

    • 这将是一个很好的解决方案,但不幸的是不适合我的任务。但是非常感谢您的回答,现在我知道我应该做什么了。而here 写道,Hibernate 可以理解不同的 getter 和列类型定义,这就是我发布这个问题的原因。
    【解决方案2】:

    为什么不编写一个实用方法,将日期作为输入并返回格式化字符串。 Hibernate 在内部使用这些 setter 和 getter,并期望实体属性和数据库字段的数据类型是兼容的。

    否则,如果您希望此格式即使在数据库中也完全相同,请将此字段设置为数据库中的varchar和实体类中的String。

    这就是你的方法的样子:

    public String getFormattedMsgDate(Date msgDate) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy MM dd HH mm ss");
        return df.format(msgDate);
    }
    

    【讨论】:

    • 从数据库中获取 bean 列表后,我在 GSON lib 的帮助下将其作为 JSON 发送,因此从 bean 中获取 String 是最简单的方法。我认为在数据库中存储 varchar instaed of timestamp 在意识形态上是不正确的。
    • 我同意,这就是我说最好你有一个实用方法为你做这件事的地方。返回一个字符串。
    猜你喜欢
    • 1970-01-01
    • 2015-01-08
    • 1970-01-01
    • 2020-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    • 1970-01-01
    相关资源
    最近更新 更多