關係映射只有正確的配置才能生成正確而有效的SQL語句,經過上一節對一對一關係的講解,咱們發現其實並不難,在關係數據庫系統中,一對多關聯基於外鍵列連接兩個表,以便子表記錄引用父錶行的主鍵。數據庫
對於一對多關係映射也存在單向和雙向關聯,在JPA中,咱們經過註解@OneToMany和@ManyToOne來進行單向或雙向關聯,雙向關聯要求目標實體映射提供@ManyToOne註解,該註解負責控制關,單向關聯經過註解@OneToMany配置更簡單,由於它是定義關係的父方,接下來咱們分別來說解單向和雙向關聯。緩存
咱們給出實體Blog和Post實體,一個博客對應下有多篇發表文章,而一篇文章只屬於特定博客,以下:session
@Entity public class Blog { @Id private Long id; @Column private String name; @OneToMany(cascade = CascadeType.ALL) private List<Post> posts = new ArrayList<>(); public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void addPost(Post post) { posts.add(post); post.setBlog(this); } public void addPosts(List<Post> posts) { for (Post p : posts) { addPost(p); } } }
@Entity public class Post { @Id @GeneratedValue private Long id; @ManyToOne private Blog blog; private String title; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Blog getBlog() { return blog; } public void setBlog(Blog blog) { this.blog = blog; } }
如上就是默認狀況下經過註解@OneToMany配置生成單向關聯的狀況,這看起來更像是多對多數據庫關聯,而不是一對多關係,理論上應該只有兩個表而不是三個表,因此咱們須要使用沒必要要的空間來存儲數據,這樣效率不高,咱們只有兩個外鍵,而不單單是一個外鍵,可是,因爲咱們最有可能對這些外鍵進行索引,所以咱們將須要兩倍的內存來緩存此關聯的索引。app
要解決生成上述額外的聯接表問題,咱們只須要在目標實體集合中繼續添加@JoinColumn註解,經過@JoinColumn註解可幫助Hibernate找出在post表中有一個blog_id外鍵列來定義此關聯。以下:post
@OneToMany(cascade = CascadeType.ALL) @JoinColumn(name = "blog_id") private List<Post> posts = new ArrayList<>();
接下來咱們打開會話來保存數據看看,以下:this
Blog blog = new Blog(); blog.setId(1L); blog.setName("Jeffcky"); Post post = new Post(); post.setTitle("hibernate4"); Post post1 = new Post(); post1.setTitle("hibernate5"); blog.addPosts(Arrays.asList(post, post1)); ...... session.save(blog);
此時咱們發現對於實體Post中的外鍵blog_id並非直接插入,而是在插入後再進行更新,這裏涉及到JPA中的實體狀態,很明顯在處理目標集合以前就進行了持久化操做,如此這樣,因爲目標實體不存儲此信息,所以Hibernate首先插入沒有外鍵的子記錄,而後在處理目標集合階段,對外鍵列進行更新。 spa
和咱們一節講解一對一關係映射同樣,咱們須要經過指定mappedBy屬性來配置雙向關聯,對目標實體集合和目標實體分別進行以下配置hibernate
@OneToMany(mappedBy = "blog", cascade = CascadeType.ALL) private List<Post> posts = new ArrayList<>();
@ManyToOne
private Blog blog;
本節咱們講解了一對多映射關係,其實和一對一關係映射差很少,本文到此結束,講完多對多關係,咱們進入到對數據的操做。3d