2013-03-21 79 views
0

我有一個Spring 3.2.1,Hibernate 4.1.9和Spring Data應用程序。我正在使用爲我的實體加入的繼承類型,層次結構如下:一個超類DomainEntity和兩個繼承自其的類的SmartElement和LowLevelEntity類,它們由其他類繼承。 SmartElement具有一組LowLevelEntities,並且該關係是雙向的。JPA-Hibernate異常「無法通過反射獲取字段值」持久

DomainEntity類

@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繼承的一個類是非常簡單的,燈飾類

@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; 
} 
} 

我收到錯誤,每當我通過堅持使用Spring的數據JPARepository含有位置通過級聯執行以下

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); 

並保存實體保存方法。

錯誤說:

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

如果我執行相同的代碼,但改變照明SmartElement我沒有錯誤

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

也沒有,如果我評論該行就發生sensor.setConnectedEntity(element);

有時候會出現一個不同的Lighting實例名稱的錯誤,這讓我認爲可能存在equals和hash問題代碼方法實現。我嘗試了不同的方法,例如here,或者只是使用沒有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爲null。如果我從數據庫中檢索兩個對象,請設置反向關係並再次保存,但不會顯示錯誤。

所以我傾向於認爲這與設置關係的擁有部分中的連接有關(LowLevelEntity類是所有者,如果我沒有弄錯的話)涉及沒有持久化的實體然後再通過級聯從位置保存實體。奇怪的是,我剛纔運行這個測試與@Repeat(50),但只有從「燈」到「kitchen_lamp」改變了smartElement名稱:

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

,並沒有錯誤。另外,在控制檯中,當智能元素具有除「kitchen_lamp」之外的任何其他名稱時,hibernate首先插入LowLevelEntity,然後嘗試插入smartElement,並使用名稱「kitchen_lamp」顛倒插入,然後無錯誤。有誰知道爲什麼會發生這種情況,如果有什麼我可以做的呢?

+0

錯誤指向model.highlevel.smartelement.lighting.Lighting.lightingLevel,但是,如果我正在閱讀代碼,它應該是model.highlevel.smartelement.lowLevelEntityCollection.connectedEntity.lightLevelLevel?我的Hybernate真的很生鏽,所以它可能只是我愚蠢。 – CodeChimp 2013-03-21 19:29:01

+0

Lighting類在'model.highlevel.smartelement.lighting'包中,我認爲Hibernate試圖以某種方式訪問​​lightingLevel字段,並且無法從其他帖子中獲得關於此類錯誤的大部分時間由完全不同的東西造成的,但Hibernate對我來說是非常新穎的,所以我沒有理由甚至從哪裏開始尋找。 – iad 2013-03-21 20:01:38

+0

只是踢,如果你從你的LightingLevelType枚舉中移除構造函數並使其變得簡單,會發生什麼? – CodeChimp 2013-03-22 10:59:15

回答

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 
} 

EDIT(第一個註釋後):

我想我現在還記得我得到的誤差在Spring數據存儲庫中的錯誤findBy方法。請檢查您的所有findBy方法!我不確定他們如何與枚舉工作,也許這是問題。

+0

我剛剛在代碼中對您提出的修改進行了測試,但錯誤仍然存​​在。他們只能找到的解決方法是隻在一側設置關係,然後在另一側手動設置關係,一旦元素被保留。不理想,但至少現在我不會再犯這個錯誤了。 – iad 2013-04-08 07:59:55

+0

好吧我想我混淆了一些東西。正如我所說的,我不確定什麼時候我發現了這個錯誤,但我確實得到了它。請參閱編輯。 – 2013-04-08 09:05:20

+0

謝謝你的回答,但我不確定它是否適用於我的情況。在我的測試中,我不會調用任何查找方法,只需要將所有元素保存到數據庫的save方法。我所具有的find方法的唯一類型是findByName和Spring Data Repository提供的findOne,它們似乎工作正常。 – iad 2013-04-08 12:41:06