Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在JPA中将java.sql.Timestamp用作真正的java.util.Date_Java_Datetime_Jpa_Persistence - Fatal编程技术网

如何在JPA中将java.sql.Timestamp用作真正的java.util.Date

如何在JPA中将java.sql.Timestamp用作真正的java.util.Date,java,datetime,jpa,persistence,Java,Datetime,Jpa,Persistence,我对毫秒日期的管理有问题。我理解需要使用时间戳来存储毫秒: @Temporal(TIMESTAMP) @Column(name="DATE_COLUMN", nullable = false) @Override public java.util.Date getDate() { return this.date; } 但是如果我不能将这个日期与java.util.date的另一个实例进行比较,除非我注意equals()调用的顺序,因为this.date实例是java.sql.Timestam

我对毫秒日期的管理有问题。我理解需要使用时间戳来存储毫秒:

@Temporal(TIMESTAMP)
@Column(name="DATE_COLUMN", nullable = false)
@Override public java.util.Date getDate() { return this.date; }
但是如果我不能将这个日期与java.util.date的另一个实例进行比较,除非我注意equals()调用的顺序,因为
this.date
实例是java.sql.Timestamp。如何从JPA获取java.util.Date?因为来自JPA的日期,即使方法签名是java.util.date,实际上也是java.sql.Timestamp的实例

java.util.Date newDate = new Date(this.date.getTime());
this.date.equals(newDate) == false
newDate.equals(this.date) == true
我已尝试在持久性类中修改我的方法:

@Override
public Date getDate() {
  return this.date == null ? null : new Date(this.date.getTime());
}
这是可行的,但对于大量数据来说效率不高

还有其他选择:

  • 我可以使用
    @PostLoad
    修改我的持久性类的设计,以便在检索到persisted日期后从该日期创建java.util.Date

  • 我想知道是否使用
    ClassTransformer
    无法得到结果


你曾经遇到过这个问题吗?我不正确的地方是什么?处理此问题的最佳方法是什么?

java.sql.Timestamp覆盖
compareTo(Date)
方法,因此使用
compareTo(…)

简而言之,
java.util.Date
java.sql.Timestamp
是相互比较的

此外,您始终可以比较
date.getTime()
,而不是对象本身


更进一步,您可以使用
long
字段来存储日期。或者甚至是一个
DateTime
(来自joda time)

根据我的经验,您不希望java.sql.Timestamp出现在您的逻辑中-正如您所指出的,它会产生许多奇怪的错误,如果您的应用程序进行序列化,它也不会变得更好

如果它与返回新java.util.Date的覆盖一起工作,那么就使用该覆盖。或者更好的选择JodaTime。你会在网上找到很多这样做的例子。我不担心这里的性能,因为您的数据库比创建新的java.util.Date对象要慢得多

编辑: 我看到您正在使用Hibernate。如果使用注释,则可以执行以下操作:

@Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime")
public DateTime getProvisionByTime() {
    return provisionByTime;
}
然后,您将从持久对象中的Jodatime获得漂亮的DateTime对象。如果您只希望有一个日期,可以像这样使用LocalDate:

@Type(type = "org.joda.time.contrib.hibernate.PersistentLocalDate")
public LocalDate getCloudExpireDate() {
    return cloudExpireDate;
}
如果您使用maven,以下依赖项应该为您设置此设置(您可能需要更新hibernate版本)


org.hibernate
冬眠
3.2.6.ga
org.hibernate
休眠注释
3.3.1.GA
乔达时间
乔达时间冬眠
1.2
乔达时间
乔达时间
1.6.1

JPA应该为java.util.Date类型的属性返回java.util.Date,@Temporal(TIMESTAMP)注释应该只影响日期的存储方式。您不应该返回java.sql.Timestamp


您使用的是什么JPA提供商?您是否在JPA参考实现EclipseLink中尝试过这一点?

TBH,我不确定这一点的确切状态,但Hibernate(您的JPA提供商,对吧?)处理
时间戳
列的方式确实可能存在问题

为了将SQL
TIMESTAMP
映射到
java.util.Date
,Hibernate使用
TimestampType
,它将实际为
java.util.Date
属性分配一个时间戳。虽然这是“合法的”,但问题是
Timestamp.equals(Object)
不对称的(到底为什么?!),这打破了
Date.equals(Object)
的语义

因此,如果
myDate
映射到SQL
TIMESTAMP
,则不能“盲目”使用
myDate.equals(someRealJavaUtilDate)
,这当然是不可接受的

但是,尽管Hibernate论坛对此进行了广泛讨论,例如在和(阅读所有页面),Hibernate用户和开发人员似乎从未就这个问题达成一致意见(参见类似问题),我只是不明白为什么

也许只是我,也许我只是错过了一些简单的东西,但这个问题对我来说是显而易见的,虽然我认为这个愚蠢的罪魁祸首,我仍然认为休眠应该屏蔽用户从这个问题。我不明白加文为什么不同意这一点

我的建议是创建一个测试用例来演示这个问题(应该非常简单),并(再次)报告这个问题,看看您是否从当前团队获得了更多的积极反馈

同时,您可以使用自定义类型自己“修复”问题,使用类似以下内容(取自论坛并按原样粘贴):


该问题对于DAO测试至关重要:

Employer employer1 = new Employer();
employer1.setName("namenamenamenamenamename");
employer1.setRegistered(new Date(1111111111)); // <- Date field

entityManager.persist(employer1);
assertNotNull(employer1.getId());

entityManager.flush();
entityManager.clear();

Employer employer2 = entityManager.find(Employer.class, employer1.getId());
assertNotNull(employer2);
assertEquals(employer1, employer2); // <- works
assertEquals(employer2, employer1); // <- fails !!!

我还没有决定-我是将这种方法用于测试和生产,还是仅用于测试。

来自持久性的日期被另一个无法修改的框架使用(太多的工作)。因为我无法修改比较过程,我需要向主系统提供java.util.Date。我想知道如何有效地转换日期?为什么需要?java.util.Date和java.sql.Timestamp是可以相互比较的。看看我的测试,方法的结果取决于调用的顺序,我没有触及这个顺序。我只需要一个真正的java.util.Date.using
compareTo(..)
应该可以工作。除此之外,您始终可以比较它们的
getTime()
,而不是对象。我希望我可以不使用,但映射是由JPA提供的…因为您使用的是hibernate,我想您可以尝试我上面提供的解决方案。hibernate是我的JPA提供程序;)这太疯狂了。正如您所建议的,我将再次尝试使用Hibernate。当我在应用程序中遇到同样的问题时,我创建了一个新问题:我刚刚有一个非常糟糕的pr版本
public class TimeMillisType extends org.hibernate.type.TimestampType {

    public Date get(ResultSet rs, String name) throws SQLException {
        Timestamp timestamp = rs.getTimestamp(name);
        if (timestamp == null) return null;
        return
            new Date(timestamp.getTime()+timestamp.getNanos()/1000000);
   }

}
Employer employer1 = new Employer();
employer1.setName("namenamenamenamenamename");
employer1.setRegistered(new Date(1111111111)); // <- Date field

entityManager.persist(employer1);
assertNotNull(employer1.getId());

entityManager.flush();
entityManager.clear();

Employer employer2 = entityManager.find(Employer.class, employer1.getId());
assertNotNull(employer2);
assertEquals(employer1, employer2); // <- works
assertEquals(employer2, employer1); // <- fails !!!
package xxx;

import org.hibernate.dialect.HSQLDialect;
import org.hibernate.type.AdaptedImmutableType;
import xxx.DateTimestampType;

import java.util.Date;

public class CustomHSQLDialect extends HSQLDialect {

    public CustomHSQLDialect() {
        addTypeOverride(DateTimestampType.INSTANCE);
        addTypeOverride(new AdaptedImmutableType<Date>(DateTimestampType.INSTANCE));
    }
}