2013-02-24 189 views
0

比方說,我有以下的商業模式:如何聲明使用Spring的JPA @OneToMany和@ManyToOne註釋數據庫映射和Hibernate

,用戶可以在N類車輛

這是我DAO/爲用戶等級:

@Entity 
@Table(name="USER") 
public @Data class User extends AbstractPersistable<Long> { 
    @OneToMany(cascade=CascadeType.PERSIST, mappedBy="owner") 
    private Set<Vehicle> vehicles = new HashSet<Vehicle>(); 
} 

這對於車輛類:

@Entity 
@Table(name="VEHICLE") 
public @Data class Vehicle extends AbstractPersistable<Long> { 
    @ManyToOne(optional = false) 
    @JoinColumn(name = "user_id") 
    User owner; 
} 

我希望能夠保存一個新的車輛進行像這樣的新用戶:

User user = new User(); 
user.setName("Fred"); // other setters omitted 

Vehicle vehicle = new Vehicle(); 
vehicle.setEngine("..."); // other setters omitted 

user.getVehicles().add(vehicle); 
userService.saveUser(user); 

userService.saveUser()是一種服務層方法,被註釋爲@Transactional並調用userRepository.save(user); (見在底部的摘錄從系統信息庫類)


現在,因爲我的解決方案有幾個問題不能按預期工作:

的是,即使可能只保存用戶對象並讓用戶對象內的Vehicle-Set自動保存?
2.這是最佳做法嗎?我知道用戶是擁有的實體。我希望在移除用戶時移除用戶的所有車輛。
3.還是我總是要做點像vehicle.setOwner(user);
4.從你的角度來看,最佳解決方案是什麼?

我讀了很多關於擁有實體和JoinColumn/mappedBy的內容。但現在我比以前更困惑了。


此外,這是從我的UserRepository的摘錄:

import org.springframework.data.jpa.repository.JpaRepository; 
import org.myproject.domains.User; 

public interface UserRepository extends JpaRepository<User, Long> { 
User findByLoginName(String loginName); 
} 

回答

0

您當然需要在您的Vehicle實體的對象中設置User的引用,否則Hibernate將無法識別該關係。

此外,我會建議使用@OneToMany

  • cascade=CascadeType.ALL進行適當的級聯操作(注意,通常你不從User觸摸Vehicle separatelly在所有)
  • fetch = FetchType.EAGER避免LazyInitializationException(注意,這你不能在你的JPA配置更多的則1個EAGER關係)
  • orphanRemoval = true對用戶的更新後的清理「不必要」的車輛
+0

你能解釋一下你的意思嗎?沒有超過1個EAGER關係*?我的用戶類實際上有4 *集*,因此有4個與獲取類型** EAGER **的OneToMany關係。我不會收到錯誤。 – 2013-02-26 16:13:09

+0

請參閱:http://www.jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple這是在Hibernate中頗爲流行的錯誤,所以最常見的解決方法是避免EAGER取。順便說一句,這是相當有趣的,爲什麼它的工作適合你,因爲在我的當前項目類中的2個EAGER實體不工作(拋出'MultipleBagFetchException:不能同時獲取多種bags') – n1ckolas 2013-02-26 16:29:39

+0

這是工作,但現在沒有EAGER我不得不使用懶惰,並會遇到*無會話*錯誤。感謝您的幫助,並指出EAGER問題。我創建了一個[新問題](http://stackoverflow.com/questions/15094109/easiest-way-to-add-vehicle-to-user-with-jpa-hibernate-using-spring)關於可能省略setOwner ()在OneToMany關係的* Many *部分(它有效地設置了用戶,只是將其稱爲擁有者)。 – 2013-02-26 16:35:29

0

CascadeType.PERSIST持續vehicles集如果只有一個堅持的情況。

我建議您使用CascadeType.ALL。因此,當您移除用戶時,vehicles將被移除,以及如果更新/保留用戶,車輛將被更新/保持。

vehicle.setOwner(用戶),如果你想從車輛訪問用戶是必要的。

+0

好吧,我將它設置爲CascadeType.ALL。 我不需要從*車輛*訪問*用戶*。我只需要擁有*用戶標識*時獲得所有車輛。看看我的4個問題,我對這個主題非常陌生,需要一些指導。 – 2013-02-24 22:03:34

+0

您也可以使用'fetch = FetchType.LAZY',它可以爲該集合啓用延遲加載。我相信hibernate文檔是一個很好的開始:http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/collections.html – ogzd 2013-02-24 22:10:25

相關問題