0

我有一个 Spring 3.2.1、Hibernate 4.1.9 和 Spring Data 应用程序。我正在为我的实体使用继承类型,层次结构如下:一个超类 DomainEntity 和两个类 SmartElement 和 LowLevelEntity 从它继承,并由其他类继承。SmartElement 具有一组 LowLevelEntities,并且关系是双向的。

域实体类

@Entity
@Table(name = "entity")
@Inheritance(strategy = InheritanceType.JOINED)
public class DomainEntity implements Serializable 
{
 @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "entity_id", unique = true)
private long uuid;

@Column(name = "entity_name", unique = true)
protected String name;

@ManyToOne()
@JoinColumn(name = "location_id")
protected Location location;


@ManyToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "state_id")
protected State state;
// getters and setters
}

SmartElment 类

@Entity
@Table(name = "smart_element")
@Inheritance(strategy = InheritanceType.JOINED)
@PrimaryKeyJoinColumn(name = "smart_element_id")
public class SmartElement extends DomainEntity implements Serializable
{
@OneToMany (mappedBy = "connectedEntity", 
        cascade = {CascadeType.ALL}, orphanRemoval = true)
protected Set<LowLevelEntity> lowLevelEntityCollection;
 // getters and setters
}

和 LowLevelEntity 类

@Entity
@Table(name = "low_level_entity")
@Inheritance(strategy = InheritanceType.JOINED)
@PrimaryKeyJoinColumn(name = "low_level_entity_id")
public class LowLevelEntity extends DomainEntity implements Serializable
{

@ManyToOne()
@JoinColumn(name = "smart_element_id")
protected SmartElement connectedEntity;

    public void setConnectedEntity(SmartElement connectedEntity)
{       
    if (connectedEntity != null)
    {
        this.connectedEntity = connectedEntity;
        this.connectedEntity.addLowLevelEntity(this);

    } else 
    {
        if (this.connectedEntity != null)
        {
            this.connectedEntity.removeLowLevelEntity(this);
        }
        this.connectedEntity = connectedEntity;
}

// other fields and getters/setters
}

现在继承自 SmartElement 的类之​​一非常简单,Lighting 类

@Entity
@Table(name = "lighting")
@PrimaryKeyJoinColumn(name = "lighting_id")
public class Lighting extends SmartElement implements Serializable
{

@Enumerated(EnumType.STRING)
protected LightingLevelType lightingLevel = LightingLevelType.NONE; 

public LightingLevelType getLightingLevel()
{
    return lightingLevel;
}

public void setLightingLevel(LightingLevelType lightingLevel)
{
    this.lightingLevel = lightingLevel;
}
}

LightingLevel 是一个枚举类

public enum LightingLevelType
{

NONE(0), QUARTER(0.25), HALF(0.5), THREE_QUARTERS(0.75), MAX(1);

private double value;

private LightingLevelType(double value)
{
    this.value = value;
}

public double getValue(){
    return value;
}
}

每当我执行以下操作时,我都会收到错误消息

SmartElement element = new Lighting("lamp", new SmartElementState(), kitchen); 
//fields inherited from the superclass DomainEntity name, state and location
LowLevelEntity sensor = new LowLevelEntity("sensor", new SensorState(), kitchen);
sensor.setConnectedEntity(element);

并通过级联保存实体,方法是使用 Spring Data JPARepository 保存方法持久保存包含位置。

错误说:

could not get a field value by reflection getter of model.highlevel.smartelement.lighting.Lighting.lightingLevel;

如果我执行相同的代码但将 Lighting 更改为 SmartElement 我没有错误

SmartElement element = new SmartElement("lamp", new SmartElementState(), kitchen); 

如果我评论该行也不会发生sensor.setConnectedEntity(element);

有时,使用不同名称的 Lighting 实例不会出错,这让我认为 equals 和 hashCode 方法的实现可能存在问题。我为此尝试了不同的方法,例如此处,或者仅使用没有 id 的元素名称,但仍然出现错误。

  @Override
public boolean equals(final Object other)
{
    if (this == other) return true;
    if (! (other instanceof DomainEntity)) return false;

    DomainEntity castOther = (DomainEntity) other;
    return new EqualsBuilder()
        .append(name, castOther.name).isEquals();

}


@Override
public int hashCode()
{
    return new HashCodeBuilder()
    .append(name).toHashCode();
}

我根本不明白发生了什么以及我做错了什么。如果有人有任何想法或遇到过这样的案例,我将非常感谢您的意见。我很抱歉这篇长篇文章,但我认为拥有代码也会更容易理解。

更新

我已经尝试了几件事来尝试找出错误的来源。

  1. 将 LightingLevelType 类中的类型更改为普通类型没有效果,错误仍然存​​在。
  2. 将 Lighting 类中的字段更改为public int type也没有效果,仅删除它可以修复错误,但这不是一个选项。
  3. 每当我尝试在 LowLevelEntity 对象中设置 connectedEntity 字段时,就会发生错误,就像sensor.setConnectedEntity(element);该方法仅执行此操作一样this.connectedEntity = connectedEntity。如果我只将对象添加到 SmartElement 集而不设置反向关系,则没有错误,但 connectedEntity 为空。如果我从数据库中检索两个对象,请设置反向关系并再次保存,则不会出现错误。

所以我倾向于认为这与在关系的拥有部分中设置连接有关(如果我没记错的话,LowLevelEntity 类是所有者)涉及尚未持久化的实体然后保存实体通过该位置的级联。奇怪的是,我刚刚使用@Repeat(50) 运行了这个测试,但只是将 smartElement 的名称从“lamp”更改为“kitchen_lamp”:

SmartElement element = new Lighting("kitchen_lamp", new SmartElementState(), kitchen);
LowLevelEntity lamp_kitchen = new LowLevelEntity("lamp_kitchen", new SensorState(), kitchen);

并且没有错误。此外,在控制台中,当智能元素具有除“kitchen_lamp”之外的任何其他名称时,休眠首先插入 LowLevelEntity,然后尝试插入 smartElement,并使用名称“kitchen_lamp”反转插入,然后没有错误。有谁知道为什么会发生这种情况,如果有什么我可以做的吗?

4

1 回答 1

1

我曾经有过类似的问题。您需要指定 ManyToOne 的 targetEntity,反之亦然。

public class LowLevelEntity extends DomainEntity implements Serializable
{
    @ManyToOne(targetEntity=SmartElement.class)
    @JoinColumn(name = "smart_element_id")
    protected SmartElement connectedEntity;
}

public class SmartElement extends DomainEntity implements Serializable
{
    @OneToMany (mappedBy = "connectedEntity", targetEntity=LowLevelEntity.class
            cascade = {CascadeType.ALL}, orphanRemoval = true)
    protected Set<LowLevelEntity> lowLevelEntityCollection;
     // getters and setters
}

编辑(在第一条评论之后):

我想我现在记得我在 Spring Data Repository 中使用错误的 findBy 方法得到了那个错误。请检查您所有的 findBy 方法!我不确定他们如何使用枚举,也许这就是问题所在。

于 2013-04-04T13:02:14.707 回答