- 定义对Entity中属性变量的访问
JPA的注解既可以写在属性上,也可以写在get方法上,两者有何区别?
复杂
Entity
类是指在
Entity
类的
getter/setter
中包含比较复杂的业务逻辑而不是仅仅返回某个属性。
在绝大部分的商业应用,开发人员都可以忽略这部分无需关心。
EJB3
持久化规范中,
针对可持久化属性定义了两种属性访问方式
(access): FIELD
和
PROPERTY
。
如果采用access=FIELD, EJB3 Persistence运行环境直接访问对象的属性变量,而不是通过getter。这种访问方式也不要求每个属性必须有getter/setter。如果需要在getter中包含商业逻辑,应该采用access=FIELD的方式。
如果采用access=PROPERTY, EJB3 Persistence运行环境将通过Entity类上的getter来访问对象的属性变量,这就要求每个属性变量要有getter/setter方法。在EJB3中,默认的属性访问方式是PROPERTY。此时getter/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即可创建对应的表。