一.Hibernate中的对象的三种状态
实体类对象在Hibernate中有3种状态
分别是瞬时,持久和脱管
瞬时 指的是没有和hibernate发生任何关系,在数据库中也没有对应的记录,一旦JVM结束,这个对象也就消失
持久 指得是一个对象和hibernate发生联系,有对应的session,并且在数据库中有对应的一条记录
脱管 指的是一个对象虽然在数据库中有对应的一条记录,但是它所对应的session已经关闭了
new 了一个Product();,在数据库中还没有对应的记录,这个时候Product对象的状态是瞬时的。
通过Session的save把该对象保存在了数据库中,该对象也和Session之间产生了联系,此时状态是持久的。
最后把Session关闭了,这个对象在数据库中虽然有对应的数据,但是已经和Session失去了联系,相当于脱离了管理,状态就是脱管的
二.表间关系
在数据库中有一些表之间是存在外键关系的, 比如我现在有一个Category表和一个Product表, 在Product表中有一列是pid是作为外键reference到Category里面的主键id, 现在我希望在Hibernate中设定一个这样的外键关系, 首先对于Product表而言, 存在一种多个product可以对应一个category的多对一关系;
对于Category表而言, 存在一种一个category可以对应多个product的一对多关系;
所以在配置文件中可以这样来声明这种关系:
//Category.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="Entity">
<class name="Category" table="category_">
<id name="id" column="id">
<generator class="native">
</generator>
</id>
<property name="name" />
<set name="products" cascade="all" lazy="false">
<key column="cid" not-null="false" />
<one-to-many class="Product" />
</set>
</class>
</hibernate-mapping>
在Category中设置一个对应的外键关系, 对应于实体类Category中的一个Set(集合, 也可以是list), 名为products
, 然后指定一对多关系, 指定到另一个实体类Product, 我在此处设置了级联为all
几种级联设置的区别:
- 级联设为
delete
: 如果删除掉了主表(Category)中的某一行, 那么对应于此行的外键都会被删除, 即所有这个category的product都会被删掉, 比如:
Category c = (Category) s.get(Category.class, 3);
s.delete(c);
- 级联设为
save-update
, 这就意味着把一些瞬时对象存储到某个Category类的集合中, 这些瞬时对象会自动持久化, 听起来比较抽象, 举个例子就是:
Category c = (Category) s.get(Category.class, 5);
Product p1 = new Product();
p1.setName("product_501");
Product p2 = new Product();
p2.setName("product_502");
Product p3 = new Product();
p3.setName("product_503");
c.getProducts().add(p1);
c.getProducts().add(p2);
c.getProducts().add(p3);
比如这样新建了一些product, 但是我并没有用s.save
来存这些对象, 而只是把他们加入到了获取的Category c中,但是实际运行发现, 设置了级联的save-update之后, 这些对象就被自动插入到了Product表中;
级联还有两种设置
-
all
: 就是同时有save-update和delete的功能; -
none
: 就是同时关闭了save-update和delete的功能, 默认就是none的;
然后我设置lazy属性为false
这个是延迟加载功能, 指的是Hibernate并不会在获取某个对象的第一瞬间加载这个对象, 而是用到这个对象的时候再加载这个对象;
除了一对多和多对一的关系之外, 还有一种是多对多的关系, 但是在数据库表的设计中是不能出现这种关系的, 往往都要用一张新表做中间映射, 来形成两个一对多的关系;
比如这样:
//User.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.how2java.pojo">
<class name="User" table="user_">
<id name="id" column="id">
<generator class="native">
</generator>
</id>
<property name="name" />
<set name="products" table="user_product" lazy="false">
<key column="uid" />
<many-to-many column="pid" class="Product" />
</set>
</class>
</hibernate-mapping>
//Product.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.how2java.pojo">
<class name="Product" table="product_">
<id name="id" column="id">
<generator class="native">
</generator>
</id>
<property name="name" />
<property name="price" />
<many-to-one name="category" class="Category" column="cid" />
<set name="users" table="user_product" lazy="false">
<key column="pid" />
<many-to-many column="uid" class="User" />
</set>
</class>
</hibernate-mapping>
设定外键集合的时候要设置table为user_product的第三张新表;