hibernate和jpa注解关联总结

[size=x-large]用hibernate和jpa annotation 大概一年多了,今天闲来无事,对他们关联关系元数据写法做一个总结。[/size]
[size=x-large]1.一对一主键关联[/size]
[size=large] 这个在实际项目中用的比较少,大部分是通过用外键做关联的,这里用用户和手机号举个例子,用户和手机号是一对一的关系,代码如下:[/size]
User实体

package com.own.model;

import java.io.Serializable;

public class Users implements Serializable{

private static final long serialVersionUID = 1381652232198529039L;
private int id;
private String username;
private String password;
private CellphoneNumber phoneNumber;
public CellphoneNumber getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(CellphoneNumber phoneNumber) {
this.phoneNumber = phoneNumber;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}


}



[size=large] 手机号实体 [/size]

package com.own.model;

import java.io.Serializable;

public class CellphoneNumber implements Serializable {

private static final long serialVersionUID = -1029364968566042141L;

private Integer cellPhoneId;
private String number;
private String attribution;//手机归属地
private String cellphonoeType;//移动或者联通
private Users user ;
public Users getUser() {
return user;
}
public void setUser(Users user) {
this.user = user;
}
public Integer getCellPhoneId() {
return cellPhoneId;
}
public void setCellPhoneId(Integer cellPhoneId) {
this.cellPhoneId = cellPhoneId;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getAttribution() {
return attribution;
}
public void setAttribution(String attribution) {
this.attribution = attribution;
}
public String getCellphonoeType() {
return cellphonoeType;
}
public void setCellphonoeType(String cellphonoeType) {
this.cellphonoeType = cellphonoeType;
}

@Override
public boolean equals(Object anotherObject){
if(anotherObject == null || anotherObject.getClass() != this.getClass()){
return false;
}
if(this == anotherObject){
return true;
}

CellphoneNumber another = (CellphoneNumber) anotherObject;
if(another.cellPhoneId.equals(this.cellPhoneId)){
return true ;
}

return false;
}

public int hashCode(){

return cellPhoneId.hashCode();
}


}


[size=large]users映射文件[/size]

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping >

<class name="com.own.model.Users" table="users" dynamic-update="true" dynamic-insert="true" >

<id name="id" column="id" >
<generator class="native"></generator>
</id>

<property name="username" column="username" ></property>
<property name="password" column="password" type="string" ></property>

<!-- 这里是一对一映射 级联为所有 -->
<one-to-one name="phoneNumber" class="com.own.model.CellphoneNumber" cascade="all" >

</one-to-one>

</class>
</hibernate-mapping>

[size=large]cellPhone映射文件[/size]

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping >

<class name="com.own.model.CellphoneNumber" table="cellphone" dynamic-update="true" dynamic-insert="true" >
<!-- 这里设置外键关联 -->
<id name="cellPhoneId" column="id" >
<generator class="foreign">
<!-- 这里设置用引用user实体的主键 -->
<param name="property">user</param>
</generator>
</id>
<property name="number" column="cellphoneNumber" ></property>
<property name="attribution" column="attribution" ></property>
<property name="cellphonoeType" column="numberType" ></property>
<!-- 加上外键约束 ,使Cellphone的主键引用user表行的主键 -->
<one-to-one name="user" constrained="true" class="com.own.model.Users" ></one-to-one>
</class>
</hibernate-mapping>

[size=large]在调用时,要设置关联关系[/size]

Users u = new Users();
u.setPassword("admin@1973");
u.setUsername("floatSnow");
CellphoneNumber cellphone = new CellphoneNumber();
cellphone.setAttribution("北京");
cellphone.setCellphonoeType("中国移动");
cellphone.setNumber("13476534589");
//设置双向关联关系
u.setPhoneNumber(cellphone);
cellphone.setUser(u);

[size=large]
jpa中使用@PrimaryKeyJoinColumn [/size]

package com.own.model;


import java.io.Serializable;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
@Entity
@org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)
@Table(name="users")
public class Users implements Serializable{
private static final long serialVersionUID = 1381652232198529039L;
private int id;
private String username;
private String password;
private CellphoneNumber cellphone;

@OneToOne(cascade={CascadeType.ALL})
@PrimaryKeyJoinColumn
public CellphoneNumber getCellphone() {
return cellphone;
}
public void setCellphone(CellphoneNumber cellphone) {
this.cellphone = cellphone;
}
@Id
@GeneratedValue
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}

@Column(name="username")
public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

@Column(name="password")
public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}


}



[size=x-large]2.一对一外键关联[/size]
[size=large] hibernate xml文件映射,在这里使用manyToOne而不是我们想像的oneToOne,还有在 user表中加一个外键,引用另一个表的主键,这里设置双向关系,在项目中根据情况而定是否设置双向关系[/size]
映射文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping >
<class name="com.own.model.Users" table="users" dynamic-update="true" dynamic-insert="true" >
<id name="id" column="id" >
<generator class="native"></generator>
</id>
<property name="username" column="username" ></property>
<property name="password" column="password" type="string" ></property>
<!-- 加上唯一约束,使这个关系成为真正的一对一 -->
<many-to-one name="phoneNumber" cascade="all" class="com.own.model.CellphoneNumber" column="cell_id"
unique="true" >
</many-to-one>
</class>
</hibernate-mapping>



[size=large] jpa 映射使用oneToone,@joinColumn有两个属性 name 和 referencedColumnName
,name是表示表中外键的列名,referencedColumnName表示外键引用的表的列名。
user实体 [/size]

@OneToOne(cascade={CascadeType.ALL})
@JoinColumn(name="cell_id",referencedColumnName="id")
public CellphoneNumber getCellphone() {
return cellphone;
}

[size=large] 手机实体类 [/size]
   
@OneToOne(mappedBy="cellphone")
public Users getU() {
return u;
}

[size=x-large]3.一对一可选关联[/size]
[size=large]有的时候我们的外键是可选的,也就是说user表的外键是可以为空的,这个时候我们可以把这中可选的关联映射到一张表,加一张中间表,表示实体的对应关系
Users实体映射文件[/size]

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping >
<class name="com.own.model.Users" table="users" dynamic-update="true" dynamic-insert="true" >
<id name="id" column="id" >
<generator class="native"></generator>
</id>
<property name="username" column="username" ></property>
<property name="password" column="password" type="string" ></property>
<!-- 加上唯一约束,使这个关系成为真正的一对一 -->
<!-- optional 告诉hibernate这个关系是可选的 ,当这个属性为空时,可以不插入关联表 -->
<join table="user_cellphoneNumber" >
<key column="user_id" unique="true" />
<many-to-one name="phoneNumber" cascade="save-update" class="com.own.model.CellphoneNumber" column="cell_id"
unique="true" >
</many-to-one>
</join>
</class>
</hibernate-mapping>

[size=large]jpa注解把属性映射到两张表,通过使用@SecondaryTable,使属性映射到一张中间表。[/size]

package com.own.model;


import java.io.Serializable;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.SecondaryTable;
import javax.persistence.Table;

import org.hibernate.transaction.JOnASTransactionManagerLookup;
@Entity
@org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)
@Table(name="users")
@SecondaryTable(name="user_cellphoneNumber",pkJoinColumns={@PrimaryKeyJoinColumn(name="user_id",referencedColumnName="id")})
public class Users implements Serializable{
private static final long serialVersionUID = 1381652232198529039L;
private int id;
private String username;
private String password;
private CellphoneNumber cellphone;
@OneToOne(cascade={CascadeType.ALL})
@JoinColumn(table="user_cellphoneNumber",name="cell_id",referencedColumnName="id")
public CellphoneNumber getCellphone() {
return cellphone;
}
public void setCellphone(CellphoneNumber cellphone) {
this.cellphone = cellphone;
}
@Id
@GeneratedValue
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}

@Column(name="username")
public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

@Column(name="password")
public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}


}

[size=x-large]4.一对多关联[/size]
[size=large] 一对多关联通过oneToMany和ManyToMany映射,这里的多段在java里用一个集合set来表示,这个用商品category和货物Goods来举例子。
one端实体Category 映射xml
[/size]

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping >
<class name="com.own.model.Category" table="category" dynamic-insert="true" dynamic-update="false" >
<id name="category_id" column="id" >
<generator class="native"></generator>
</id>
<property name="categoryName" column="category_name" type="string" ></property>

<set name="goodsSet" inverse="true" cascade="save-update" > <!-- 用key column 的名字表示关联表的外键的名称 -->
<key column="category_id" />
<one-to-many class="com.own.model.Goods" />
</set>
</class>
</hibernate-mapping>

[size=large]many端的映射文件[/size]

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping >
<class name="com.own.model.Goods" table="goods" dynamic-insert="true" dynamic-update="false" >
<id name="id" column="goods_id" >
<generator class="native"></generator>
</id>
<property name="price" column="goods_price" type="double" ></property>
<property name="goodsName" column="goods_name" type="string" ></property>
<property name="goodsDescription" column="goods_description" type="string" ></property>
<many-to-one name="category" fetch="join" class="com.own.model.Category" column="category_id" >
</many-to-one>
</class>

</hibernate-mapping>

[size=large]jpa元数据注解
Category实体[/size]

package com.own.model;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)
@Table(name="category")
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
private Integer category_id;
private String categoryName;
private Set<Goods> goodsSet = new HashSet<Goods>();

@OneToMany(mappedBy="category",cascade={CascadeType.ALL})
public Set<Goods> getGoodsSet() {
return goodsSet;
}
public void setGoodsSet(Set<Goods> goodsSet) {
this.goodsSet = goodsSet;
}
@Id
@GeneratedValue
@Column(name="id")
public Integer getCategory_id() {
return category_id;
}
public void setCategory_id(Integer categoryId) {
category_id = categoryId;
}

@Column(name="category_name")
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}



}


[size=large]Goods实体[/size]

package com.own.model;


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.Table;

@Entity
@org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)
@Table(name="goods")
public class Goods implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String goodsName;
private Double price;
private String goodsDescription;
private Category category;
@ManyToOne
@JoinColumn(name="category_id",referencedColumnName="id")
public Category getCategory() {
return category;
}

public void setCategory(Category category) {
this.category = category;
}

public Goods(){}

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="goods_id")
public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

@Column(name="goods_name",length=40,nullable=false)
public String getGoodsName() {
return goodsName;
}
public void setGoodsName(String goodsName) {
this.goodsName = goodsName;
}

@Column(name="goods_price")
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}

@Column(name="goods_description")
public String getGoodsDescription() {
return goodsDescription;
}
public void setGoodsDescription(String goodsDescription) {
this.goodsDescription = goodsDescription;
}


@Override
public boolean equals(Object o) {

if(o == null || o.getClass() != this.getClass()){
return false;
}

if(o == this){
return true;
}

Goods goods = (Goods) o;

if(id == null ? goods.id == null : this.id.equals(goods.id)){
return true;
}


return false;
}

/*@Override
public int hashCode() {
//return this.id.hashCode();
return
}*/

}



[size=x-large]5.多对多关联[/size]
[size=large] 多对多关联用manyToMany来映射,这里用学生和选的课程,它们是多对多的关联,多对对
关联通常需要一张中间表,这个表就两字段,学生id和课程id(这里中间表就两个字段)
在java中用两set集合来表示
student 映射文件[/size]

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping >
<class name="com.own.model.Student" table="student" dynamic-update="true" dynamic-insert="true" >
<id name="studentId" column="id" >
<generator class="native"></generator>
</id>
<property name="studentName" column="student_name" ></property>
<property name="studentNum" column="student_no" type="string" ></property>
<set name="cosrseSet" table="student_course" >
<!-- 引用当前实体主键的外键名称 -->
<key column="student_id" />
<many-to-many column="course_id" class="com.own.model.Course" ></many-to-many>
</set>
</class>
</hibernate-mapping>

[size=large]course映射文件[/size]

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping >
<class name="com.own.model.Course" table="course" dynamic-update="true" dynamic-insert="true" >
<id name="courseId" column="id" >
<generator class="native"></generator>
</id>
<property name="courseName" column="course_name" ></property>
<property name="courseNum" column="course_no" ></property>

<set name="studentSet" inverse="true" cascade="all" table="student_course" >
<key column="course_id" />
<many-to-many column="student_id" class="com.own.model.Student" ></many-to-many>
</set>
</class>
</hibernate-mapping>

[size=large]jpa元数据
Student实体[/size]

package com.own.model;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@Entity
@Table(name="student")
public class Student implements Serializable {

private static final long serialVersionUID = 1L;
private Integer studentId;
private String studentName;
private String studentNum;
private Set<Course> cosrseSet = new HashSet<Course>();
@ManyToMany
@JoinTable(name="student_course",joinColumns={@JoinColumn(name="student_id")},
inverseJoinColumns={@JoinColumn(name="course_id")})
public Set<Course> getCosrseSet() {
return cosrseSet;
}
public void setCosrseSet(Set<Course> cosrseSet) {
this.cosrseSet = cosrseSet;
}

@Id
@GeneratedValue
@Column(name="id")
public Integer getStudentId() {
return studentId;
}
public void setStudentId(Integer studentId) {
this.studentId = studentId;
}

@Column(name="student_name")
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}

@Column(name="student_no")
public String getStudentNum() {
return studentNum;
}
public void setStudentNum(String studentNum) {
this.studentNum = studentNum;
}

}


[size=large]Course实体[/size]

package com.own.model;

import java.io.Serializable;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@Entity
@Table(name="course")
public class Course implements Serializable {
private static final long serialVersionUID = 1L;
private Integer courseId;
private String courseNum;
private String courseName;
private Set<Student> studentSet = new HashSet<Student>();

@ManyToMany(mappedBy="cosrseSet")
public Set<Student> getStudentSet() {
return studentSet;
}
public void setStudentSet(Set<Student> studentSet) {
this.studentSet = studentSet;
}
@Id
@GeneratedValue
@Column(name="id")
public Integer getCourseId() {
return courseId;
}
public void setCourseId(Integer courseId) {
this.courseId = courseId;
}

@Column(name="course_no")
public String getCourseNum() {
return courseNum;
}
public void setCourseNum(String courseNum) {
this.courseNum = courseNum;
}

@Column(name="course_name")
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}

/* @Override
public boolean equals(Object o) {
if(o == null || o.getClass() != Course.class){
return false;
}

if(o == this){
return true;
}

Course another = (Course)o;
if(courseId == null ? another.courseId == null : courseId.equals(another.courseId)){
return true;
}

return false;

}

@Override
public int hashCode() {
return super.hashCode();
// return 1;
}*/


}


[size=large]在多对对关联的情况下,用的是set集合,实体要实现hashcode和equals,不然在更新关联表的时候会更新不了,比如学生不在选择这门课程,从set集合中remove掉这个课程,然后更新这个学生实体,代码如下,在不实现hashcode和equals更新不会成功,只有实现了才可以,hibernate返回了自己写的集合,PersistenceSet而不是HashSet,这也是为什么我们在实体中写set接口,不能写HashSet ... = new HashSet,要用 Set ... = new HashSet 。[/size]

tc = session.beginTransaction();
Student s1 = (Student) session.get(Student.class,9) ;
Course c = new Course();
s1.getCosrseSet().remove(c);
session.update(s1);//更新学生的选课
tc.commit();

[size=large]
最后讲解一下cascade和inverse这两个属性,刚用hibernate的时候也比较不理解,首先这两个属性没有任何关系,cascade表示级联,就是被关联的一段,比如cascade='save-update',级联保存和更新,在设置了cascade的端,保存这个对象,会一并保存关联的一端,省去了我们写保存关联端的代码,inverse表示有谁来维护关联,在一段设置inverse=true,则有关联对来维护关联关系,比如上面的例子,在course端设置了inverse=true,则有student来维护中间表,只有当插入student的时候,才向中间表插入数据,如果都设置inverse=true则会插入重复数据,如果不设置,则会出错,在jpa元数据注解中 用mappedBy来表示有那方来维护关联关系[/size]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值