2013-02-01 51 views
0

我使用Spring 3.2和hibernate-core 4.1.4以及hibernate-jpa-2.0.1。應用程序資源文件具有所有正確的對象。使用Hibernate插入子對象不會返回完整對象

我有一個子對象RoleEntity,它有兩個父母:User和Award,所以userId和awardId是已存在的外鍵,並且必須存在才能創建角色實體。

public class RoleEntity implements Serializable 
{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "role_id") 
    private long roleId; 

    @Column(name = "role_description") 
    private String roleDescription; 

    @Column(name = "role_name") 
    private String roleName; 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name = "user_id") 
    private UserEntity user; 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name = "award_id") 
    private AwardEntity award; 

    ... getters/setters 
    ... hash/equals/toString 
} 

吾道插入看上去很簡單:

@Override 
public RoleEntity saveRoleEntity(RoleEntity role) 
{ 
    logger.debug("saveRoleEntity: role=" + role); 
    return role; 
} 

我有單元測試此代碼,我可以確認的是,當我選擇一個現有的角色ID,我完全可以拿回加載的對象,與用戶和獎項完全填充。

然而,當我插入新的角色,我做到以下幾點:

  1. 集角色ID爲0,角色介紹...
  2. 創建userEntity,只有已設定的ID,這個ID存在,是不是新的
  3. 創建awardEntity,只設置ID,這個ID已經存在,並不是新

我可以成功地做了保存,這是偉大!!!!適用於我。 而在新對象返回中,我可以清楚地看到新角色Id返回給我了! RoleEntity的所有其他字段,如描述,在那裏。

但是,我還需要的是RoleEntity的User和Award字段被完全填充,就好像我在插入後做了select一樣。這甚至有可能嗎?

我寧願不做一個選擇給用戶和獎表獲得這些對象,然後將它們分配給這個對象,但如果我必須這樣做,那很好。

如果我需要提供更多信息,請告訴我。 感謝您提前提供任何幫助。

回答

1

試試這個辦法:在這裏

sess.save(role);
sess.flush(); //force the SQL INSERT
sess.refresh(role);

+0

謝謝!這非常有幫助,並解決了我的問題! – tjholmes66

0

兩件事情。首先你不應該創建新的具有已知ID的實體來使用這個ID。這種方法是一個等待發生的事故:具有此ID的實體已經存在,並且由於此重複密鑰,您將遇到ConstraintViolationExceptionNonUniqueObjectException

如果您想使用具有已知ID但不想從數據庫中選擇完整實體的實體,使用Hibernate可以使用代理

UserEntity user = session.load(UserEntity.class, userId); 
AwardEntity award = session.load(AwardEntity.class, awardId); 

這將不會命中數據庫來選擇實體,但會返回一個代理(包裝已知的id)。在同一個會議上,你可以比使用代理喜歡全實體並創建新的RoleEntity

RoleEntity role = new RoleEntity(); 
role.setUser(user); 
role.setAward(award); 
session.save(role); 

的第二件事是:如何休眠知道你的實體的非ID特性而無需訪問數據庫! ? Hibernate能做到這一點的唯一方法是使用Second Level Cache(L2C),但從你的問題來看,我認爲沒有L2C。

即使您的@ManyToOne關聯是渴望獲取 Hibernate必須命中數據庫才能填充相應的實體。所以,你可以使用的方法從@波格丹的答案,並插入

session.save(role); 
session.refresh(role); 

後重新加載角色和相關的用戶和獎勵的實體,但這將有超過選擇先以分配他們根據實體沒有性能優勢新角色

UserEntity user = session.get(UserEntity.class, userId); 
AwardEntity award = session.get(AwardEntity.class, awardId);  

這將立即訪問數據庫並填充實體(或者如果與ID給出行存在返回null)。

請注意,當您使用代理服務器時,您可以在同一個會話中填充實體點播。只要訪問非id屬性,就會從數據庫中選擇相應的實體。

這就是說,我建議看看Hibernate docs以便更好地理解。如果你想在生產級別上使用Hibernate,你還應該閱讀一本好的Hibernate書籍,如Java Persistence with Hibernate

希望這會有所幫助。