我有一个 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();
}
我根本不明白发生了什么以及我做错了什么。如果有人有任何想法或遇到过这样的案例,我将非常感谢您的意见。我很抱歉这篇长篇文章,但我认为拥有代码也会更容易理解。
更新
我已经尝试了几件事来尝试找出错误的来源。
- 将 LightingLevelType 类中的类型更改为普通类型没有效果,错误仍然存在。
- 将 Lighting 类中的字段更改为
public int type
也没有效果,仅删除它可以修复错误,但这不是一个选项。 - 每当我尝试在 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”反转插入,然后没有错误。有谁知道为什么会发生这种情况,如果有什么我可以做的吗?