【问题标题】:missing rows with empty value in hibernate query在休眠查询中缺少具有空值的行
【发布时间】:2015-09-08 04:06:24
【问题描述】:

我有两个带有外键引用的表:

Comm TABLE:

+----+------------+
| ID |    NAME    |
+----+------------+
|  1 | comm name1 |
|  2 | comm name2 |
|  3 | comm name3 |
+----+------------+

LOCATION TABLE: - COMM_ID FK to  Comm --> id

+---------+------+-----+
| COMM_ID | FORM | TO  |
+---------+------+-----+
|       1 | 720  | 721 |
|       1 | 725  |     |
|       1 |      | 766 |
|       1 |      |     |
|       2 | 766  | 225 |
|       3 | 766  | 222 |
+---------+------+-----+

问题是 Hibernate 返回我的通讯对象 在SET<location> 中缺少location 没有FROM TO 的所有行(例如 LOCATION 表中 COMM_ID = 1 的最后一行)都丢失了。

否则(如果只有FROMTO 之一)返回该行... 为什么?

Comm对象:

@ElementCollection
@CollectionTable(name="LOCATION",joinColumns=@JoinColumn(name="COMM_ID"))
 public Set<LOCATION> getLocations(){
    return locations;
 }
 public void setLocations(Set<LOCATION> locations){
    this.locations=locations;
 }

Location类:

@Embeddable
class Location implements java.io.Serializable {

    private BigDecimal fromLocationId;
    private BigDecimal toLocationId;

    public Location() {
    }

    public Location(BigDecimal fromLocationId, BigDecimal toLocationId) {
        this.fromLocationId = fromLocationId;
        this.toLocationId = toLocationId;
    }

    @Column(name="FROM", nullable=true, precision=22, scale=0)
    public BigDecimal getFromLocationId() {
        return this.fromLocationId;
    }

    public void setFromLocationId(BigDecimal fromLocationId) {
        this.fromLocationId = fromLocationId;
    }

    @Column(name="TO", nullable=true, precision=22, scale=0)
    public BigDecimal getToLocationId() {
        return this.toLocationId;
    }

    public void setToLocationId(BigDecimal toLocationId) {
        this.toLocationId = toLocationId;
    }

    @Override
    public int hashCode() {
        return com.google.common.base.Objects.hashCode(fromLocationId, toLocationId);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        final LOCATION  other = (LOCATION) obj;
        return com.google.common.base.Objects.equal(this.fromLocationId, other.fromLocationId) && com.google.common.base.Objects.equal(this.toLocationId, other.toLocationId);
    }
}

我正在使用 Hibernate - 4.3.6

日志:

org.hibernate.SQL - 
    select
        locations0_.COMM_ID as COMM_ID1_2_0_,
        locations0_.FROM as FROM2_8_0_,
        locations0_.TO as TO4_8_0_
    from
        LOCATION  locations0_ 
    where
        locations0_.COMM_ID=1

我在我的数据库中检查了它,它返回了正确的结果。

【问题讨论】:

  • 我错过了什么吗?你的数据显示 from 和 to 是字符串,但你映射说它们应该是数字????
  • 请发布整个LOCATION 课程。由于您使用的是Set,因此必须正确覆盖equalshashCode 方法。
  • public boolean equals(com.google.common.base.Object obj) 这看起来不对。请发布 full 课程。并检查您是否发布了真实代码。
  • 两件事:首先为什么“comm_id”变量丢失了?你不需要吗?如果该表的两行具有不同的“comm_id”,但都没有“from”或“to”,则可能会出现问题,因此它们仍然“逻辑”等于您的程序。第二:我认为com.google.common.base.Objects.equal(this.fromLocationId, other.fromLocationId) 在这里很危险。因为它应该调用BigDecimal#equals,并且这个实现对“相等”实例非常严格。要检查这是否是问题,请测试this implementation 或使用List 而不是Set
  • 我改变了我的“equal”方法并没有帮助,无论如何我在“equal”方法中添加了断点并且没有命中。 (当位置返回时,它会命中这个断点)

标签: java hibernate


【解决方案1】:

可嵌入对象的数据包含在其父表的多个列中。由于没有单个字段值,因此无法知道父级对可嵌入对象的引用是否为空。可以假设,如果可嵌入对象的每个字段值都为空,则引用应该为空,但是没有办法用所有空值来表示可嵌入对象。 JPA 不允许嵌入项为空,但一些 JPA 提供者可能支持这一点。

Hibernate : 加载实体时,如果嵌入对象中的所有列都为空,则嵌入引用设置为空。

更多信息click here

所以当你保存可为空的可嵌入值时,休眠允许保存但在获取休眠时丢弃那些可为空的行。

【讨论】:

    【解决方案2】:

    其实输出没有错。我认为您只是混淆了embeddableentity。因为,据我所知。如果有很多实体使用相同的字段,您只能使用 embeddable 类来简化实体的开发。

    据我所知,hashcodeequals 方法确实将所有这六个记录视为不同的记录。所以,我认为你想要的是将Location 类变成这样的东西。

    @Entity
    class Location implements java.io.Serializable {
    
    private Long commId;
    private BigDecimal fromLocationId;
    private BigDecimal toLocationId;
    
    // all the setter getter here
    
    @Override
    public int hashCode() {
        return com.google.common.base.Objects.hashCode(commId);
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        final LOCATION  other = (LOCATION) obj;
        return com.google.common.base.Objects.equal(this.commId, other.commId);
    }
    }
    

    或者,当然您可以让 get 方法返回一个 List,然后如果该行缺少 fromto 值,则删除该行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-21
      • 1970-01-01
      • 1970-01-01
      • 2013-11-17
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 2015-02-06
      相关资源
      最近更新 更多