遇到的问题:
在hibernate一对多的注解中,由于没有添加mappedBy=“多端的关联属性名”,导致在更新数据时,外键被置空(null),意思是由多的一端来维护关系。(一般由有外键的一方来维护)
解决方法:
一:Author(作者) 多:Book(书籍)
其代码分别如下:
Author的pojo代码:
package com.jason.domain;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
@Entity
@Table(name = "Author")
public class Author implements Serializable{
private Integer id;
private String authorName;
private Set<Book> bookList;
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="generator")
@SequenceGenerator(sequenceName="Author_SEQ",
name="generator",initialValue=1,allocationSize=1)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name = "authorName", length = 30)
public String getAuthorName() {
return authorName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
@OneToMany(mappedBy="author") //添加mappedBy="author"解决,但注意不能与@JoinColumn(name="author_id")共存
@Cascade(value= {CascadeType.ALL}) //设定级联关系
public Set<Book> getBookList() {
return bookList;
}
public void setBookList(Set<Book> bookList) {
this.bookList = bookList;
}
@Override
public String toString() {
return "Author [id=" + id + ", authorName=" + authorName + "]";
}
}
Book的pojo代码:
package com.jason.domain;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
@Entity
@Table(name = "Book")
public class Book implements Serializable{
private Integer id;
private String bookName;
private Float price;
private Author author;
public Book() {
}
public Book(String bookName, Float price) {
this.bookName = bookName;
this.price = price;
}
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="generator")
@SequenceGenerator(sequenceName="Book_SEQ",
name="generator",initialValue=1,allocationSize=1)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name = "bookName", length = 30)
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
//scale:小数位数
@Column(name = "price",scale = 1)
public Float getPrice() {
return price;
}
public void setPrice(Float price) {
this.price = price;
}
@ManyToOne
@JoinColumn(name="author_id")
@Cascade(CascadeType.ALL)
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
@Override
public String toString() {
return "Book [id=" + id + ", bookName=" + bookName + ", price=" + price + ", author=" + author + "]";
}
}
详细知识:
mappedBy:1、只有@OneToOne,@OneToMany,@ManyToMany上才有mappedBy属性,ManyToOne不存在该属性;
2、mappedBy标签一定是定义在被拥有方的(被控方),他指向拥有方;
3、mappedBy的含义,应该理解为,拥有方能够自动维护跟被拥有方的关系,当然,如果从被拥有方,通过手工强行来维护拥有方的关系也是可以做到的;
4、mappedBy跟joinColumn/JoinTable总是处于互斥的一方,可以理解为正是由于拥有方的关联被拥有方的字段存在,拥有方才拥有了被拥有方。mappedBy这方定义JoinColumn/JoinTable总是失效的,不会建立对应的字段或者表。
下面是一个例子:
人跟身份证双向关联
人跟身份证双向关联
在person里面定义的注释代码:
@OneToOne(cascade = CascadeTye.ALL,optional = true)
public IDCard getIdCard(){
return idCard;
}
在idcard里面定义的注释代码:
@OneToOne(cascade = CascadeType.ALL,mappedBy = "idCard",optional = false)
public Person getPerson(){
return person;
}
解释:
多了一个mappedBy这个方法,他表示什么呢?它表示当前所在表和Person的关系是定义在Person里面的idCard这个成员上面的,他表示此表是一对一关系中的从表,也就是关系是在person表中维护的,这是最重要的。Person表是关系的维护者,有主导权,它有个外键指向IDCard。
我们也可以让主导权在IDCard上面,也就是让他产生一个指向Person的外键,这也是可以的,但是最好让Person来维护整个关系,这样更符合我们的思维。
我们也可以看到在Person里面的IDCard是注释optional=true,也就是说一个人是可以没有身份证的,但是一个身份证是不可以没有人的,所以在IDCard里面注释Person的时候,optional=false了,这样就可以防止一个空的身份证记录进数据库。
我们也可以让主导权在IDCard上面,也就是让他产生一个指向Person的外键,这也是可以的,但是最好让Person来维护整个关系,这样更符合我们的思维。
我们也可以看到在Person里面的IDCard是注释optional=true,也就是说一个人是可以没有身份证的,但是一个身份证是不可以没有人的,所以在IDCard里面注释Person的时候,optional=false了,这样就可以防止一个空的身份证记录进数据库。