`
lovethisworld
  • 浏览: 52630 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JPA双向关系配置&复合主键

    博客分类:
  • JPA
阅读更多
  • 定义对Entity中属性变量的访问
  JPA的注解既可以写在属性上,也可以写在get方法上,两者有何区别?
  复杂Entity类是指在Entity类的getter/setter中包含比较复杂的业务逻辑而不是仅仅返回某个属性。在绝大部分的商业应用,开发人员都可以忽略这部分无需关心。EJB3持久化规范中,针对可持久化属性定义了两种属性访问方式(access): FIELDPROPERTY
  如果采用access=FIELD, EJB3 Persistence运行环境直接访问对象的属性变量,而不是通过getter。这种访问方式也不要求每个属性必须有getter/setter。如果需要在getter中包含商业逻辑,应该采用access=FIELD的方式。
  如果采用access=PROPERTY, EJB3 Persistence运行环境将通过Entity类上的getter来访问对象的属性变量,这就要求每个属性变量要有getter/setter方法。在EJB3中,默认的属性访问方式是PROPERTYgetter/setter方法的逻辑应该尽量简单。
  一个简单的例子如下:
@Entity
public class User {
	private int id;
	// @Column(length=10) // 注解在此处则表中字段为name
	private String name;
	
	public User() {}

	@Id @GeneratedValue
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	@Column(length=10)	// 注解在此处则表中字段为name1
	public String getName1() {
		return name;
	}
	public void setName1(String name) {
		this.name = name;
	}
}
  • 双向一对一关系配置
  每个公民都对应一个身份证号,两者的关系是一对一关系,构建实体Person和PID:
@Entity
public class Person {
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private int id;

	@Column(length=10,nullable=false)
	private String name;
	
	@OneToOne(optional=false,cascade=CascadeType.ALL)
	@JoinColumn(name="pid_id")
	private PID id;

        public Person() {
		this.name = "lzz";
	}
	public Person(String name) {
		this.name = name;
	}
	// getter and setter
}
@Entity
public class PID {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private int id;
	
	private String pid;
	
	@OneToOne(mappedBy="pid",cascade={CascadeType.PERSIST
			 ,CascadeType.MERGE,CascadeType.REFRESH}
	         ,optional=false)//指定为关系的被维护端,这里的optional可以去掉,因为外键不允许为空
	private Person person;

	public PID(String pid) {
		this.pid = pid;
	}
        public PID() {
		this.pid = "xxx";
	}
	// getter and setter
}
  • 双向一对多关系配置
  每次购物总会购买多样商品,订单和商品是一对多的关系,构建实体Order和Item
@Entity
public class Order_ {
	
	/**
	 * 双向的一对多关系里面,多的一方为关系的维护端。 关系的维护端负责外键字段(记录)的更新; 关系的被维护端是没有权力更新外键字段(记录)的。
	 */
	@Id	@GeneratedValue
	private int id;

	@Column(nullable = false)
	private float amount;

	/**
	 * 延迟加载必须保证em是开着的 如果是ToMany则默认延迟加载 如果是ToOne则默认是立即加载
	 * 通过mappedBy声明关系的维护端,这里是指明在OrderItem类里面的哪个属性来维护关系
	 * 在哪个类出现mappedBy则表明该实体是关系被维护端。
	 */
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "order")
	private List<Item> items = new ArrayList<Item>();

	// 建立关系维护
	public void addOrderItem(Item item) {
		item.setOrder(this);// 关系维护端orderItem来设置,维护关系
		this.items.add(item);
		amount += item.getPrice();
	}
        // getter and setter
}
 注:在试验过程中,如果该实体取名Order时总是无法生成表,不知何故?
@Entity
public class Item {
	/**
	 * 双向的一对多关系里面,多的一方为关系的维护端。 关系的维护端负责外键字段(记录)的更新; 关系的被维护端是没有权力更新外键字段(记录)的。
	 */
	@Id	@GeneratedValue
	private int id;

	@Column(nullable = false)
	private String name;

	@Column(nullable = false)
	private float price;

	@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH }, optional = false)
	@JoinColumn(name="order_id")
	private Order_ order;

	// getter and setter
}
  • 双向多对多关系配置
老师和学生是多对多关系,一个学生有多个老师,一个老师也有多个学生,构建实体Teacher和Student:
@Entity
public class Teacher {
	@Id	@GeneratedValue
	private Integer id;
	
	@Column(length = 30, nullable = false)
	private String name;
	
	// 关系被维护端
	@ManyToMany(mappedBy = "teachers", cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
	private Set<Student> student = new HashSet<Student>();

        // getter and setter
}

 

@Entity
public class Student {
	@Id 	@GeneratedValue
	private Integer id;
	
	@Column(length=30,nullable=false)
	private String name;
	
	//一般在多对多很少用到级联的操作。
	/**
	 * inverseJoinColumns关系被维护端的外键在中间表中的定义
	 * JoinColumns       关系维护端的外键在中间表中的定义
	 */
	@ManyToMany(cascade=CascadeType.REFRESH)
	@JoinTable(name="student_teacher"
	           ,inverseJoinColumns=@JoinColumn(name="teacherid")
	           ,joinColumns=@JoinColumn(name="studentid"))
	private Set<Teacher> teachers=new HashSet<Teacher>();

        // getter and setter
}
  • 复合主键
@Entity
public class Couple {

	@EmbeddedId
	private CouplePK couple;
	private String address;
	
        // getter and setter
}
   复合类:必须为public,实现Serializable,由无参构造函数
@Embeddable
public class CouplePK implements Serializable {
	
	private Person husband;
	private Person wife;
		
	public CouplePK() {}

        //getter and setter
}
 构建好实体后,通过Persistence.createEntityManagerFactory("test")加载hibernate即可创建对应的表。
 
分享到:
评论
3 楼 cobraw 2015-04-27  
请教复合主键一对多关联的问题:

以上述Couple为基础, 现假设有Children,如何建立Couple与Children的一对多关联?
(一对父母有多个孩子)

@Entity
public class Children{

@EmbeddedId
private ChildrenPK children;
private int meeting;//孩子看望父母的次数

        // getter and setter
}

@Embeddable
public class ChildrenPK implements Serializable {

private Person husband;
private Person wife;
        private Person child;

public ChildrenPK() {}

        //getter and setter
}
2 楼 lovethisworld 2010-08-01  
hareamao 写道
order是sql的关键字

是哦,哈哈,谢谢~
1 楼 hareamao 2010-08-01  
order是sql的关键字

相关推荐

Global site tag (gtag.js) - Google Analytics