以客户和订单之间的关系为例
客户表为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() {
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)