Hibernate介绍:http://blog.csdn.net/ljheee/article/details/52475798
Hibernate操作一对一关系:http://blog.csdn.net/ljheee/article/details/52593662
Hibernate操作一对多关系:
"一对多"是最普遍的映射关系,简单来讲就如产品和类别的关系。一个类别下可有多个产品,多个产品可同属一个类别。
本例---业务说明
本实例涉及的表为CATEGORIES(类别表)和PRODUCTS(商品表)。
规定每个类别下可有多个商品;每个商品被划分到某一个类别。
产品表中的类别ID引用类别表中的外键。
下面进入主题:使用Hibernate操作一对多关系
创建一个Java工程。创建实体类Product,其类中需要有一个字段标识是哪一个类别。
public class Product {
private StringproductNum;
private StringproductName;
private StringcateogryName;//用一个String类型标识产品类别
}
此处用一个String类型标识产品类别,也是可行的,不过通常不会这么做,因为在数据库存储“产品”一条条记录的时候,表中的这一列存在冗余。所以推荐下面一中方案:
public class Product {
private String id;
private String name;
private Categorycategory;//是一个自定义类
// Getters &Setters ...
}
public class Category {//自定义类--类别
private Long id;
private stringcategoryName;
// Getters & Setters ...
}
数据库表
<!– Product类映射文件 - ->
<class name="Product"table="PRODUCTS">
<id name="id" column="PRODUCT_NUM">
<generator class="native"></generator>
</id>
<property name="name"column="PRODUCT_NAME"></property>
<many-to-one name="category"
column="CATEGORY_ID"
class="Category"
cascade="save-update">
</many-to-one>
</class>
该映射文件中,前两个分别指定了PRODUCTS表中的主键列和产品名;<many-to-one name="category"指定产品类Product中category字段类型是class="Category"。
<!-- Category类映射文件 - ->
<class name="Category"table="CATEGORIES">
<id name="id" column="CATEGORY_ID"type="java.lang.Long">
<generator class="native"></generator>
</id>
<property name="path"column="CATEGORY_PATH"></property>
</class>
这样就建立了产品和类别的单向一对多关联,即:从某个产品,单向可知该产品所属类别。
但是可能会有这样的需求,我想查询“儿童玩具”这个类别下的成品有哪些,并按价格排序,这时候就需要建立产品和类别的双向一对多关联:由产品可知所属类别,由某个类别也可得该类别下的所有产品。
Category 类修改如下:
public class Category {
private Long id;
private stringcategoryName;
private Set products;//所属该类别的产品集合
// Getters & Setters ...
}
<!-- Category类映射文件 - ->
<class name="Category"table="CATEGORIES">
<id name="id" column="CATEGORY_ID"type="java.lang.Long">
<generator class="native"></generator>
</id>
<property name="path"column="CATEGORY_PATH"></property>
<set name="products" cascade="save-update">
<key column="CATEGORY_ID"></key>
<one-to-many class="Product"/>
</set>
</class>
该映射文件中<setname="products"指定products集合中,放的都是class="Product"类型。
工程源代码
1、实体类Product
package com.ljheee.orm;
/**
* 产品类
* @author ljheee
*
*/
public class Product {
private Long id;
private String name;
private int price;
private Category category;
public Product() {
}
public Product(String name, int price, Category category) {
super();
this.name = name;
this.price = price;
this.category = category;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
@Override
public String toString() {
return "Product [id=" + id + ", name=" + name + ", price=" + price + ", category=" + category + "]";
}
}
产品类Product的映射文件:Product.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2016-9-3 9:30:29 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="com.ljheee.orm.Product" table="PRODUCT">
<id name="id" type="java.lang.Long">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="price" type="int">
<column name="PRICE" />
</property>
<many-to-one name="category" class="com.ljheee.orm.Category" fetch="join">
<column name="CATEGORY_ID" />
</many-to-one>
</class>
</hibernate-mapping>
2、[产品]类别Category
package com.ljheee.orm;
import java.util.HashSet;
import java.util.Set;
/**
* [产品]类别
* @author ljheee
*
*/
public class Category {
private Long id;
private String title;//类别名
private String desc;//类别描述
//不加此行是单向连接,由产品可知是属于哪个类别。
/**
* 产品集合
* 即该类别下,所属的所有产品
*/
private Set<Product> products = new HashSet<>();//集合没有序号
public void addProduct(Product p){
products.add(p);
}
public Set<Product> getProducts() {
return products;
}
public void setProducts(Set<Product> products) {
this.products = products;
}
public Category() {
}
//对象状态
//1 瞬时状态
//2 持久化状态
//3 托管状态
public Category(String title, String desc) {
super();
this.title = title;
this.desc = desc;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Category [id=" + id + ", title=" + title + ", desc=" + desc + "]";
}
}
Category的映射文件:Category.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2016-9-3 9:30:29 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<!-- 左边类名,映射右边指定的关系表 -->
<class name="com.ljheee.orm.Category" table="CATEGORY">
<!--类的id属性,作数据库ID字段列,generator生成类别class="increment"字段增长-->
<id name="id" type="java.lang.Long">
<column name="ID" />
<generator class="native" />
</id>
<property name="title" type="java.lang.String">
<column name="TITLE" />
</property>
<property name="desc" type="java.lang.String">
<column name="summary" />
</property>
<!-- Set<Product>建立双向关联 -->
<set name="products" cascade="save-update" fetch="join" lazy="true">
<key>
<!--CATEGORY_ID是表Product的外键 -->
<column name="CATEGORY_ID"></column>
</key>
<one-to-many class="com.ljheee.orm.Product"/>
</set>
</class>
</hibernate-mapping>
3、工程配置文件:hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!-- 这个cfg配置文件里,可有多个会话工.厂;如果就默认的一个,则不指定name -->
<session-factory >
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">abc</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mypersons</property>
<property name="hibernate.connection.username">abc</property>
<property name="hibernate.default_schema">mypersons</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 第一次运行,根据配置文件,自动创建表 -->
<!-- <property name="hbm2ddl.auto">create</property> -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<mapping resource="com/ljheee/orm/Category.hbm.xml"/>
<mapping resource="com/ljheee/orm/Product.hbm.xml"/>
</session-factory>
</hibernate-configuration>
这些完成后,创建一个测试类,在main方法中获得会话Session,即可对增删改查数据记录了。
如:添加一个商品"lenovoN220",并且将其划到"笔记本"类别下
//相互绑定关系,在数据库表中体现为主外键
pro.setCategory(ctg);
ctg.getProducts().add(pro);
并且这里用session只save了产品pro,并没有save类别ctg,这是因为做了级联。
Hibernate配置文件3个重要属性
1、cascade(级联)
1. 级联的意思是指定两个对象之间的操作联动关系,对一个对象执行了操作之后,对其指定的级联对象也需要执行相同的操作
2. 总共可以取值为:all、none、save-update、delete
3. all-代表在所有的情况下都执行级联操作
4. none-在所有情况下都不执行级联操作
5. save-update-在保存和更新的时候执行级联操作
6. delete-在删除的时候执行级联操作
2、lazy – 延迟加载(懒加载)
lazy – 延迟加载(懒加载),一般用于集合的抓取策略,也就是说只在需要用到的情况下,再发出select语句,将其相关的对象查询出来
set 默认lazy属性的值是true,即hibernate会自动使用懒加载策略,以提高性能
举例说明
<set name="students“ lazy=“false”>
<keycolumn="classesid" ></key>
<one-to-manyclass="com.bjsxt.hibernate.Student" />
</set>
3、inverse属性
inverse – 标记由哪一方来维护关联关系(双向关联中会用到)
1. inverse默认值为false
2. 如果inverse设置为true,表示将由对方维护两者之间的关联关系
举例说明
<set name="students“ lazy=“false”inverse=“true”>
<keycolumn="classesid" ></key>
<one-to-manyclass="com.bjsxt.hibernate.Student" />
</set>
完整工程:https://github.com/ljheee/ProductORM