您的位置:首页 > 其它

Hibernate -- 映射实体关联关系(一对多关联关系)

2017-02-09 20:01 501 查看
以客户和订单之间的关系为例

客户表为t_customers,订单表为t_orders

选择t_orders为主表, t_customers为从表

1.编写实体类 Orders

/**
* Hibernate的注解类包名为javax.persistence
*/

@Entity                   // 将一个Java类声明为一个POJO类(实体类)
@Table(name = "t_orders") //声明了该实体映射所指定的表,该类属性name指定表名
public class Orders implements java.io.Serializable {

private Integer oid;
private String oname;
private String oprice;

private Customers customer;// 持有一个客户对象,在many端持有one端对象

public Orders() {

}

public Orders(String oname, String oprice) {
this.oname = oname;
this.oprice = oprice;
}

@Id   //声明了该实体的标识属性,该属性对应表中的主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//声明了主键的生成策略,该注解的strategy属性指定了主键生成策略,默认值为GenerationType.AUTO  GenerationType.IDENTITY, 对于MySQL、SQL Server这样的数据库选择自增长的注解生成策略
@Column(name = "oid")  //声明了属性到列的映射
public Integer getOid() {
return oid;
}

public void setOid(Integer oid) {
this.oid = oid;
}

@Column(name = "o_name")
public String getOname() {
return oname;
}

public void setOname(String oname) {
this.oname = oname;
}

@Column(name = "o_price")
public String getOprice() {

4000
return oprice;
}

public void setOprice(String oprice) {
this.oprice = oprice;
}

@ManyToOne(fetch = FetchType.LAZY, targetEntity = Customers.class, cascade = CascadeType.ALL)
@JoinColumn(name = "cid") //为了映射外键列的信息,需要在外键列所对应的实体定义@JoinColumn注解,name为指定该外键列的列名
public Customers getCustomer() {
return customer;
}

public void setCustomer(Customers customer) {
this.customer = customer;
}

}


2.编写实体类 Customers

@Entity
@Table(name = "t_customers")
public class Customers implements java.io.Serializable {

private Integer cid;
private String cname;
private String ctel;
private String carea;

private Set<Orders> ords = new HashSet<Orders>();// 在one方,加入多方的集合,必须set类型。

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cid")
public Integer getCid() {
return cid;
}

public void setCid(Integer cid) {
this.cid = cid;
}

@Column(name = "c_name")
public String getCname() {
return cname;
}

public void setCname(String cname) {
this.cname = cname;
}

@Column(name = "c_tel")
public String getCtel() {
return ctel;
}

public void setCtel(String ctel) {
this.ctel = ctel;
}

@Column(name = "c_area")
public String getCarea() {
return carea;
}

public void setCarea(String carea) {
this.carea = carea;
}

@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.LAZY,
targetEntity = Orders.class)  // mappedBy属性指定关联对象的属性名,表明由对方Order维护关联关系
public Set<Orders> getOrds() {
return ords;
}

public void setOrds(Set<Orders> ords) {
this.ords = ords;
}

}


3.编写测试文件 DemoOneToMany

public class DemoOneToMany {

public static void main(String[] args) {

savess();
System.out.println("操作成功!");
}

private static void savess() {
Session s = HibernateSessionFactory.getSession();// 建立会话工厂,获得会话!

Transaction t = s.beginTransaction();// 事务。事务的四大特性:原子性,一致性,隔离性,持久性

Customers c = new Customers();
c.setCname("马超");
c.setCtel("13223587890");
c.setCarea("三国时代");

Orders o1 = new Orders();
o1.setOname("冰洁羽绒服");
o1.setOprice("788");
o1.setCustomer(c);

Orders o2 = new Orders();
o2.setOname("意尔康皮鞋");
o2.setOprice("380");
o2.setCustomer(c);

o1.setCustomer(c);
o2.setCustomer(c);

s.persist(o1);
s.persist(o2);

t.commit();
s.close();

}
}


4.配置文件



5.知识点汇总

如果没有在属性上添加@Column,则表明该属性所映射字段的名称与其同名 注解既可放在属性上,也可放在属性的getter方法上。

cascade指定对关联实体所采用的级联策略,该级联策略支持如下五个属性值:

CascadeType.ALL包含所有;

CascadeType.PERSIST只有A类新增时,会级联B对象新增。若B对象在数据库存(跟新)在则抛异常(让B变为持久态)

CascadeType.MERGE指A类新增或者变化,会级联B对象(新增或者变化)

CascadeType.REFRESH级联保存:当多个用户同时作操作一个实体,为了用户取到的数据是实时的,在用实体中的数据之前就可以调用一下refresh()方法

指定抓取关联实体时的抓取策略,该属性支持以下两个属性值:

FetchType.EAGER:抓取实体时,立即抓取关联实体,这是默认值

FetchType.LAZY:抓取实体时,延迟抓取关联实体,等到真正用到关联实体时才去抓取

由于在@ManyToOne中设置了cascade=CascadeType.All,所以当保存

Order实体时将级联保存它的Customer关联实体

hibernate 之所以提供与save()功能几乎完全类似的persist()方法,一方面是为了照顾JPA的用法习惯。

另一方面,save()和 persist()方法还有一个区别: 使用 save()

方法保存持久化对象时,该方法返回该持久化对象的标识属性值(即对应记录的主键值); 但使用 persist()

方法来保存持久化对象时,该方法没有任何返回值。 因为 save() 方法需要立即返回持久化对象的标识属性,所以程序执行 save()

会立即将持久化对象对应的数据插入数据库; 而 persist() 则保证当它在一个事物外部被调用时,并不立即转换成 insert 语句,

这个功能是很有用的,尤其当我们封装一个长会话流程的时候,persist() 方法就显得尤为重要了。

主要内容区别:

1,persist把一个瞬态的实例持久化,但是并”不保证”标识符(identifier主键对应的属性)被立刻填入到持久化实例中,标识符的填入可能被推迟到flush的时候。

2,save, 把一个瞬态的实例持久化标识符,及时的产生,它要返回标识符,所以它会立即执行Sql insert

6.小秘籍

一对多,在many方实体类(如order)中需要定义一个one方属性,而在one方实体类无须存放many方对象集合属性。

一对多,维护权在many方,配置注解 @ManyToOne(fetch = FetchType.LAZY, targetEntity = Customers.class, cascade = CascadeType.ALL) @JoinColumn(name = “cid”)

则one方配置注解 @OneToMany(mappedBy = “customer”, cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = Orders.class)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: