【问题标题】:Cannot persist hashmap with JPA无法使用 JPA 持久化 hashmap
【发布时间】:2011-12-01 07:22:15
【问题描述】:

我正在努力尝试使用以下代码将地图持久化到 SQLserver 并不断收到以下错误:

* 原因:com.microsoft.sqlserver.jdbc.SQLServerException:无效的对象名称“OnlineReport_availabilities”。 *

为此,我使用 Play 框架 JPA 之前已经设法使用类似的代码来持久化 Maps。我尝试在数据库中手动创建表,以查看名称是否有任何问题,但一切正常。

我在这里做了一些非常规或不正确的事情?


   @Entity
    public class OnlineReport extends Model {

    @Temporal(TemporalType.DATE)
    public Date date;

    @ElementCollection
    public Map<Date, Double> availabilities;

    public OnlineReport(){
        this.date = new Date();
        this.availabilities = new HashMap<Date, Double>();         
    }

    public void addAvailability(double availability){
        TreeSet<Date> set = new TreeSet(availabilities.entrySet());

        Date lastEntry = null;
        if(!set.isEmpty())
            lastEntry = set.last();

        Date now = new Date();
        if(lastEntry != null){
            //Add availibility every 10mn
            if(DateUtil.getMinutesBetween(lastEntry, now) >= 10){
                availabilities.put(now, availability);
                save();
            }
        } else {
            availabilities.put(now, availability);
            save();
        }
    }
}


更新。

在 debugSQL 中运行 JPA 我注意到以下错误:

错误~不成功:创建表 OnlineReport_availabilities(OnlineReport_id numeric(19,0) not null,availabilities double precision null,availabilities_KEY datetime null,主键(OnlineReport_id,availabilities_KEY))

错误 ~ 无法在表 'OnlineReport_availabilities' 中为可为空的列定义 PRIMARY KEY 约束。

我的印象是我缺少一些“可用性”的注释定义。

【问题讨论】:

  • 该表是否确实存在于数据库中? SQLServer 中表名的大小是否有限制?
  • 该表不存在,但 JPA 和 play 通常会自动创建表。我尝试手动重新创建具有相同名称和虚拟字段的表,没有问题。
  • 我注意到 OnlineReport 表上的“可用性”存储为 varbinaries(255)。我不确定这与 hibermate 应该创建的 OnlineReport_availabilities 表有什么关系。
  • 你班级的主键是什么?您应该明确定义一个。我倾向于尽可能使用自动生成的。

标签: java hibernate collections playframework jpa-2.0


【解决方案1】:

您可能没有这样的表,或者无法通过正在使用的连接访问它。 db 中的对象(表、字段等)名称是否区分大小写?

所以,在您更新后,我们知道您为什么没有桌子。看起来它无法为作为键的一部分的列创建 not null 约束。 SQL Server 的方言失败,因为您的映射很小,但正确。您可以尝试通过添加以下注释来强制它:

@MapKeyColumn(columnDefinition = "datetime not null")

当然,如果每毫秒可能有多个条目,则将日期时间作为键的一部分会产生问题。

【讨论】:

  • 不,sql server 表名不区分大小写。
  • 如果数据库被创建为不区分大小写,那么这当然不是问题。然后你可以试试这个列定义是否强制它不允许键列为空。
  • Tx,这个问题实际上是通过使用非空键手动创建表来解决的。我将尝试使用注释。时间应该不是问题,因为每个条目都是 10m 间隔。