hibernate 6 映射集合和实体关联 | hibernate 实战(第二版) 第6章映射集合和实体关联 | 笔记
2011-10-22 21:37
363 查看
值类型的set、bag、list和map
选择集合接口:
1、使用<Set>元素映射java.util.Set。使用java.util.HashSet初始化集合。它是无序且不允许重复。
2、使用<Set>映射java.util.SortedSet。且sort属性可以设置成比较器或者用于内存的排序的自然顺序。使用
java.util.TreeSet实例初始化集合。
3、使用<list>映射java.util.List。在集合表中用一个额外的索引列保存每个元素的位置。使用java.util.ArrayList初始化。
4、使用<bag>或者<idbag>映射java.util.Collection。java没有Bag接口或者实现;然而,java.util.Collection允许包
语义。hibernate支持持久化的包。使用java.util.ArrayList初始化包集合。
5、使用<map>映射java.util.Map,保存键和值对。使用java.util.HashMap初始化属性。
6、使用<map>映射java.util.SortedMap。且sort属性可以设置为比较器或者用于内存排序的自然顺序。使用
java.util.TreeMap实例初始化该集合。
7、hibernate使用<primitve-array>和<array>支持数组。但是他们很少使用在领域模型中。因为hibernate无法
包装数组属性,没有字节码基础设施(BCI),就失去了延迟加载,以及持久化集合优化过的脏检查、基本
的便利和性能特性。
映射Set:
无序不允许重复:
类:
view
plaincopy
to clipboardprint?
/**
*
实现String类型的set集合,非class(实体bean)集合
*/
public class Item implements Serializable
{
private int itemId;
private String
itemName;
//不允许重复
private Set<String>
images = new HashSet<String>();
配置文件:
view
plaincopy
to clipboardprint?
<hibernate-mapping package="cn.partner4java.set">
<class name="Item">
<id
name="itemId">
<generator class="native"/>
</id>
<property
name="itemName" type="string"/>
<!--
映射了一个无序的string集合 -->
<set
name="images" table="ITEM_IMAGES">
<key
column="ITEM_ID"></key>
<element
type="string" column="FILENAME" not-null="true"></element>
</set>
</class>
</hibernate-mapping>
插入2:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().add("image1");
item.getImages().add("image1");
hibernate 打印 sql:
Hibernate: insert into Item (itemName) values (?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, FILENAME) values (?, ?)
插入2:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().add("image1");
item.getImages().add("image2");
hibernate打印sql:
Hibernate: insert into Item (itemName) values (?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, FILENAME) values (?, ?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, FILENAME) values (?, ?)
映射bag:
有序允许重复:
类:
view
plaincopy
to clipboardprint?
/**
*
允许重复元素的无序集合bag
*/
public class Item implements Serializable
{
private Integer
itemId;
private String
itemName;
private Collection<String>
images = new ArrayList<String>();
配置文件:
view
plaincopy
to clipboardprint?
<hibernate-mapping package="cn.partner4java.connection">
<class name="Item">
<id
name="itemId" type="integer">
<generator class="native"/>
</id>
<property
name="itemName" type="string"/>
<!--
映射了一个无序的string集合 -->
<idbag
name="images" table="ITEM_IMAGES">
<!--
给集合加一个id -->
<collection-id
type="integer" column="ITEM_IMAGE_ID">
<generator class="increment"></generator>
</collection-id>
<key
column="ITEM_ID"></key>
<element
type="string" column="FILENAME" not-null="true"></element>
</idbag>
</class>
</hibernate-mapping>
插入:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().add("image1");
item.getImages().add("image1");
hibernate打印sql:
Hibernate: insert into Item (itemName) values (?)
Hibernate: select max(ITEM_IMAGE_ID) from ITEM_IMAGES
Hibernate: insert into ITEM_IMAGES (ITEM_ID, ITEM_IMAGE_ID, FILENAME) values (?, ?, ?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, ITEM_IMAGE_ID, FILENAME) values (?, ?, ?)
注意:
view
plaincopy
to clipboardprint?
<collection-id
type="integer" column="ITEM_IMAGE_ID">
<generator class="increment"></generator>
</collection-id>
这里的generator给的类型是increment,如果mysql给的是native或者identity会报错:
org.hibernate.id.IdentifierGeneratorFactory$2 cannot be cast to java.lang.Integer
但是oracle使用native、sequence不会报错(应该是这个版本的hibernate的bug)
**删除**:
(如果没记错的话,类类型的set集合,是不会删除子集的,只默认级联一的一端)
这里是都级联删除的
view
plaincopy
to clipboardprint?
Item
item = (Item) session.get(Item.class, 2);
session.delete(item);
Hibernate: select item0_.itemId as itemId0_0_, item0_.itemName as itemName0_0_ from Item item0_ where item0_.itemId=?
Hibernate: delete from ITEM_IMAGES where ITEM_ID=?
Hibernate: delete from Item where itemId=?
映射list(允许重复,有序):
view
plaincopy
to clipboardprint?
/**
*
映射list
*/
public class Item implements Serializable
{
private Integer
itemId;
private String
itemName;
private List<String>
images = new ArrayList<String>();
配置文件:
view
plaincopy
to clipboardprint?
<hibernate-mapping package="cn.partner4java.list">
<class name="Item">
<id
name="itemId" type="integer">
<generator class="native"/>
</id>
<property
name="itemName" type="string"/>
<list
name="images" table="ITEM_IMAGES">
<key
column="ITEM_ID"></key>
<!-- 2.X兼容方式,不在使用<index></index>
-->
<list-index
column="POSITION"></list-index>
<element
type="string" column="FILENAME" not-null="true"></element>
</list>
</class>
</hibernate-mapping>
插入:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().add("image1");
item.getImages().add("image1");
hibernate打印sql:
Hibernate: insert into Item (itemName) values (?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, POSITION, FILENAME) values (?, ?, ?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, POSITION, FILENAME) values (?, ?, ?)
(POSITION记录的就是list的指针位置0、1、2...)
删除:
view
plaincopy
to clipboardprint?
Item
item = (Item) session.get(Item.class, 2);
session.delete(item);
Hibernate: select item0_.itemId as itemId0_0_, item0_.itemName as itemName0_0_ from Item item0_ where item0_.itemId=?
Hibernate: delete from ITEM_IMAGES where ITEM_ID=?
Hibernate: delete from Item where itemId=?
映射map(无序,不允许重复):
类:
view
plaincopy
to clipboardprint?
/**
*
映射map
*/
public class Item implements Serializable
{
private int itemId;
private String
itemName;
private Map<String,
String> images = new HashMap<String,
String>();
配置文件:
view
plaincopy
to clipboardprint?
<hibernate-mapping package="cn.partner4java.map">
<class name="Item">
<id
name="itemId">
<generator class="native"/>
</id>
<property
name="itemName" type="string"/>
<map
name="images" table="ITEM_IMAGES">
<key
column="ITEM_ID"></key>
<map-key
type="string" column="IMAGENAME"></map-key>
<element
type="string" column="FILENAME" not-null="true"/>
</map>
</class>
</hibernate-mapping>
插入:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().put("imagename1", "filename1");
item.getImages().put("imagename1", "filename1");
hibernate打印sql:
Hibernate: insert into Item (itemName) values (?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, IMAGENAME, FILENAME) values (?, ?, ?)
映射sortedmap,排序集合:
类:
view
plaincopy
to clipboardprint?
/**
*
映射sortedmap,排序集合
*/
public class Item implements Serializable
{
private int itemId;
private String
itemName;
private SortedMap<String,
String> images = new TreeMap<String,
String>();
配置文件:
view
plaincopy
to clipboardprint?
<hibernate-mapping package="cn.partner4java.sortedmap">
<class name="Item">
<id
name="itemId">
<generator class="native"/>
</id>
<property
name="itemName" type="string"/>
<!--
sort="natural"是按照string进行排序,也可实现java.util.Comparator
如:srot="cn.partner4java.MyComp" -->
<map
name="images" table="ITEM_IMAGES" sort="natural">
<key
column="ITEM_ID"></key>
<map-key
type="string" column="IMAGENAME"></map-key>
<element
type="string" column="FILENAME" not-null="true"/>
</map>
</class>
</hibernate-mapping>
插入:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().put("imagename2", "filename2");
item.getImages().put("imagename1", "filename1");
hibernate打印sql:
Hibernate: insert into Item (itemName) values (?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, IMAGENAME, FILENAME) values (?, ?, ?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, IMAGENAME, FILENAME) values (?, ?, ?)
(数据中,images1的插入顺序是按照string排序的,也就是先插入了imagename1)
order-by:
view
plaincopy
to clipboardprint?
<map
name="images" table="ITEM_IMAGES" order-by="">
<set
name="images" table="ITEM_IMAGES" order-by="FILENAME
asc">
order-by属性中的表达式是SQL order by 子句的一个片段,可以按集合表的任何列进行排序。
组件的集合
组件的集合被类似地映射到JDK值类型的集合。唯一的区别是用<composite-element>代替
<element>标签。
类:
view
plaincopy
to clipboardprint?
/**
*
映射集合
*/
public class Item implements Serializable
{
private int itemId;
private String
itemName;
private Set<ItemImage>
images = new HashSet<ItemImage>();
public class ItemImage implements Serializable
{
private String
imageName;
private String
fileName;
private int sizeX;
private int sizeY;
配置文件:
view
plaincopy
to clipboardprint?
<hibernate-mapping package="cn.partner4java.composite">
<class name="Item">
<!--
如果你不给它明确指定column="ITEM_ID",他是不会截取大写字母添加下划线的,不知道为什么,可能是现在的版本就这样了
-->
<id
name="itemId" column="ITEM_ID">
<generator class="native"/>
</id>
<property
name="itemName" type="string" column="ITEM_NAME"/>
<set
name="images" table="ITEM_IMAGE" order-by="IMAGE_NAME
asc">
<!--
是定义 ITEM_IMAGE 表,与主表关联的字段名称,和主表的id无任何关系,也就是这里可以随意写 -->
<key
column="ITEM_ID"></key>
<composite-element class="ItemImage">
<property
name="imageName" column="IMAGE_NAME" not-null="true"></property>
<property
name="fileName" column="FILE_NAME" not-null="true"></property>
<property
name="sizeX" column="SIZE_X" not-null="true"></property>
<property
name="sizeY" column="SIZE_Y" not-null="true"></property>
</composite-element>
</set>
</class>
</hibernate-mapping>
插入:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().add(new ItemImage("imageName", "fileName", 1, 2));
hibernate打印sql:
Hibernate: insert into Item (ITEM_NAME) values (?)
Hibernate: insert into ITEM_IMAGE (ITEM_ID, IMAGE_NAME, FILE_NAME, SIZE_X, SIZE_Y) values (?, ?, ?, ?, ?)
用注解映射集合
基本的集合映射:
映射无序的set集合:
类:
view
plaincopy
to clipboardprint?
/**
*
基本的集合映射(映射无序的set集合)
*
@author partner4java
*
*/
@Entity
public class Item implements Serializable
{
@Id
@GeneratedValue
@Column(name="item_id")
private int itemId;
@Column(name="item_name",length=100)
private String
itemName;
//hibernate
annotation 包对包含值类型元素的集合映射支持非标准的注解,
//主要是CollectionOfElements
@CollectionOfElements(targetElement=java.lang.String.class)
//指定加入的表名,和加入表的对应列名
@JoinTable(name="ITEM_IMAGE",joinColumns=@JoinColumn(name="ITEM_ID"))
@Column(name="FILENAME",nullable=false)
private Set<String>
images = new HashSet<String>();
有序的list集合:
view
plaincopy
to clipboardprint?
/**
*
有序的list集合
*
@author partner4java
*
*/
@Entity
public class Item implements Serializable
{
@Id
@GeneratedValue
@Column(name="ITEM_ID")
private Integer
itemId;
@Column(name="ITEM_NAME",length=100)
private String
itemName;
@CollectionOfElements(targetElement=java.lang.String.class)
@JoinTable(name="ITEM_IMAGE",joinColumns=@JoinColumn(name="ITME_ID"))
//为了映射持久化list,需要添加
IndexColumn,该索引列默认基数为0
@IndexColumn(name="POSITION",base=1)
@Column(name="FILENAME")
private List<String>
images = new ArrayList<String>();
映射持久化的映射Map:
view
plaincopy
to clipboardprint?
/**
*
映射持久化的映射Map
*
@author partner4java
*
*/
@Entity
public class Item implements Serializable
{
@Id
@GeneratedValue
@Column(name="ITEM_ID")
private Integer
itemId;
@Column(name="ITEM_NAME",length=100)
private String
itemName;
@CollectionOfElements
@JoinTable(name="ITEM_IMAGE",joinColumns=@JoinColumn(name="ITEM_ID"))
@MapKey(columns=@Column(name="IMAGENAME"))
@Column(name="FILENAME")
private Map<String,
String> images = new HashMap<String,
String>();
排序集合:
view
plaincopy
to clipboardprint?
/**
*
排序集合
*
@author partner4java
*
*/
@Entity
public class Item implements Serializable
{
@Id
@GeneratedValue
@Column(name="ITEM_ID")
private Integer
itemId;
@Column(name="ITEM_NAME")
private String
itemName;
@CollectionOfElements
@JoinTable(name="ITEM_IMAGE",joinColumns=@JoinColumn(name="ITEM_ID"))
//排序
@Sort(type=SortType.NATURAL)
@Column(name="FILENAME")
private SortedSet<String>
images = new TreeSet<String>();
添加order by排序:
view
plaincopy
to clipboardprint?
/**
*
添加order by排序
*
@author partner4java
*
*/
@Entity
public class Item implements Serializable
{
@Id
@GeneratedValue
@Column(name="ITEM_ID")
private Integer
itemId;
@Column(name="ITEM_NAME")
private String
itemName;
@CollectionOfElements(targetElement=java.lang.String.class)
@JoinTable(name="ITEM_IMAGE",joinColumns=@JoinColumn(name="ITEM_ID"))
@Column(name="FILENAME")
//对有序列号的list类型是不起作用的
@OrderBy(clause="FILENAME
asc")
private Set<String>
images = new HashSet<String>();
映射父子关系
许多开发人员在开始使用hibernate时要尝试的第一件事就是父子关系的映射。
这通常是你第一次遇到集合,也是你第一次必须思考实体和值类型之间的区别,
否则会在ORM的复杂性中迷失。
下面简要的阐述了关系映射:
多样性:
在描述和分类关联时,我们通常使用术语多样性。在我们的例子中,多样性只是两小块信息:
一个特定的Item可以有不止一个Bid吗?
一个特定的Bid可以有不止一个Item吗?
看一眼领域模型之后,就可以推断:从Bid到Item的关联是一个多对一的关联。回忆一下,关联是有方向性的,
把从Item到Bid的方向关联归为一对多的关联。
另外只有两种可能:多对多和一对一。
在对象持久化的上下文中,我们不关注多个(many)是否意味着两个或者最大五个或者没有限制:只关注大多数
关联的选择性;不特别关心是否需要关联的实例,或者关联的另一侧是否可以为空。但是,这些是影响你在关系
数据库Schema中选择完整性规则和在SQL DDL中定义约束的重要方面。
最简单的可能关联:
从Bid到Item的关联(反之亦然)是一种最简单的可能实体关联的例子。两个类中有两个属性。一个是引用的集合,另一个是单个引用。
首先,这是Bid的Java类实现:
view
plaincopy
to clipboardprint?
public class Bid{
...
private Item
item;
...
}
接下来是这个关联的Hibernate映射:
view
plaincopy
to clipboardprint?
<class
name="Bid"
table="BID">
...
<many-to-one
name="item"
column="ITEM_ID"
class="Item"
not-null="true"/>
</class>
如果拿这个与本章前面的集合映射进行比较,会发现你用一个不同的元素<one-to-many>映射了集合内容。这表明集合没有包含值类型实例,
而是包含了对实体实例的引用。现在hibernate知道如何处理共享的引用和被关联对象的生命周期(他禁用了值类型实例的所有隐式依赖的
生命周期)。hibernate也知道用给集合的表语目标实体类被映射到的表相同--<set>映射不需要table属性。
由<key>元素定义的列映射的BID表的外键列ITEM_ID,即已经在关系的另一侧映射的同一个列。
注意,表Schema并没有改变:它与之前你的映射关联的多彻一样。但是,有一点不同:not null="true"不见了。问题是现在有两个不同的单项
关联映射到同一个外键列。
哪一侧控制这个列呢?
在运行时,同一个外键值有两个不同的内存表示法:Bid的item属性和由Item保存的bids集合的一个元素。假设应用程序修改了关联,例如通过
在addBid()方法的这个片段中对货品添加出价:
bid.setItem(item);
bids.add(bid);
在这种情况下hibernate侦测到内存持久化实例的两处变化。从数据库的观点来看,只有一个值必须更新以体现这些变化:BID表的ITEM_ID列。
hibernate没有透明地侦测到引用同一个数据库列的两处变化,因为此时还没有做任何事来表明这是一个双向的关联。换句话说,已经映射了
同一个列两次,hibernate始终需要知道这一点,因为它无法自动侦测到这个重复。
在关联映射中还需要做一件事情,就是是他成为真正的双向关联映射。inverse属性告诉hibernate,集合是<many-to-one>关联在另一侧的一个镜像:
也就是inverse一侧的改变不会引起数据库的改变,另一侧的改变才会引起数据库的改变。也就是把inverse标识在被维护的一端。
选择集合接口:
1、使用<Set>元素映射java.util.Set。使用java.util.HashSet初始化集合。它是无序且不允许重复。
2、使用<Set>映射java.util.SortedSet。且sort属性可以设置成比较器或者用于内存的排序的自然顺序。使用
java.util.TreeSet实例初始化集合。
3、使用<list>映射java.util.List。在集合表中用一个额外的索引列保存每个元素的位置。使用java.util.ArrayList初始化。
4、使用<bag>或者<idbag>映射java.util.Collection。java没有Bag接口或者实现;然而,java.util.Collection允许包
语义。hibernate支持持久化的包。使用java.util.ArrayList初始化包集合。
5、使用<map>映射java.util.Map,保存键和值对。使用java.util.HashMap初始化属性。
6、使用<map>映射java.util.SortedMap。且sort属性可以设置为比较器或者用于内存排序的自然顺序。使用
java.util.TreeMap实例初始化该集合。
7、hibernate使用<primitve-array>和<array>支持数组。但是他们很少使用在领域模型中。因为hibernate无法
包装数组属性,没有字节码基础设施(BCI),就失去了延迟加载,以及持久化集合优化过的脏检查、基本
的便利和性能特性。
映射Set:
无序不允许重复:
类:
view
plaincopy
to clipboardprint?
/**
*
实现String类型的set集合,非class(实体bean)集合
*/
public class Item implements Serializable
{
private int itemId;
private String
itemName;
//不允许重复
private Set<String>
images = new HashSet<String>();
配置文件:
view
plaincopy
to clipboardprint?
<hibernate-mapping package="cn.partner4java.set">
<class name="Item">
<id
name="itemId">
<generator class="native"/>
</id>
<property
name="itemName" type="string"/>
<!--
映射了一个无序的string集合 -->
<set
name="images" table="ITEM_IMAGES">
<key
column="ITEM_ID"></key>
<element
type="string" column="FILENAME" not-null="true"></element>
</set>
</class>
</hibernate-mapping>
插入2:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().add("image1");
item.getImages().add("image1");
hibernate 打印 sql:
Hibernate: insert into Item (itemName) values (?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, FILENAME) values (?, ?)
插入2:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().add("image1");
item.getImages().add("image2");
hibernate打印sql:
Hibernate: insert into Item (itemName) values (?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, FILENAME) values (?, ?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, FILENAME) values (?, ?)
映射bag:
有序允许重复:
类:
view
plaincopy
to clipboardprint?
/**
*
允许重复元素的无序集合bag
*/
public class Item implements Serializable
{
private Integer
itemId;
private String
itemName;
private Collection<String>
images = new ArrayList<String>();
配置文件:
view
plaincopy
to clipboardprint?
<hibernate-mapping package="cn.partner4java.connection">
<class name="Item">
<id
name="itemId" type="integer">
<generator class="native"/>
</id>
<property
name="itemName" type="string"/>
<!--
映射了一个无序的string集合 -->
<idbag
name="images" table="ITEM_IMAGES">
<!--
给集合加一个id -->
<collection-id
type="integer" column="ITEM_IMAGE_ID">
<generator class="increment"></generator>
</collection-id>
<key
column="ITEM_ID"></key>
<element
type="string" column="FILENAME" not-null="true"></element>
</idbag>
</class>
</hibernate-mapping>
插入:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().add("image1");
item.getImages().add("image1");
hibernate打印sql:
Hibernate: insert into Item (itemName) values (?)
Hibernate: select max(ITEM_IMAGE_ID) from ITEM_IMAGES
Hibernate: insert into ITEM_IMAGES (ITEM_ID, ITEM_IMAGE_ID, FILENAME) values (?, ?, ?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, ITEM_IMAGE_ID, FILENAME) values (?, ?, ?)
注意:
view
plaincopy
to clipboardprint?
<collection-id
type="integer" column="ITEM_IMAGE_ID">
<generator class="increment"></generator>
</collection-id>
这里的generator给的类型是increment,如果mysql给的是native或者identity会报错:
org.hibernate.id.IdentifierGeneratorFactory$2 cannot be cast to java.lang.Integer
但是oracle使用native、sequence不会报错(应该是这个版本的hibernate的bug)
**删除**:
(如果没记错的话,类类型的set集合,是不会删除子集的,只默认级联一的一端)
这里是都级联删除的
view
plaincopy
to clipboardprint?
Item
item = (Item) session.get(Item.class, 2);
session.delete(item);
Hibernate: select item0_.itemId as itemId0_0_, item0_.itemName as itemName0_0_ from Item item0_ where item0_.itemId=?
Hibernate: delete from ITEM_IMAGES where ITEM_ID=?
Hibernate: delete from Item where itemId=?
映射list(允许重复,有序):
view
plaincopy
to clipboardprint?
/**
*
映射list
*/
public class Item implements Serializable
{
private Integer
itemId;
private String
itemName;
private List<String>
images = new ArrayList<String>();
配置文件:
view
plaincopy
to clipboardprint?
<hibernate-mapping package="cn.partner4java.list">
<class name="Item">
<id
name="itemId" type="integer">
<generator class="native"/>
</id>
<property
name="itemName" type="string"/>
<list
name="images" table="ITEM_IMAGES">
<key
column="ITEM_ID"></key>
<!-- 2.X兼容方式,不在使用<index></index>
-->
<list-index
column="POSITION"></list-index>
<element
type="string" column="FILENAME" not-null="true"></element>
</list>
</class>
</hibernate-mapping>
插入:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().add("image1");
item.getImages().add("image1");
hibernate打印sql:
Hibernate: insert into Item (itemName) values (?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, POSITION, FILENAME) values (?, ?, ?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, POSITION, FILENAME) values (?, ?, ?)
(POSITION记录的就是list的指针位置0、1、2...)
删除:
view
plaincopy
to clipboardprint?
Item
item = (Item) session.get(Item.class, 2);
session.delete(item);
Hibernate: select item0_.itemId as itemId0_0_, item0_.itemName as itemName0_0_ from Item item0_ where item0_.itemId=?
Hibernate: delete from ITEM_IMAGES where ITEM_ID=?
Hibernate: delete from Item where itemId=?
映射map(无序,不允许重复):
类:
view
plaincopy
to clipboardprint?
/**
*
映射map
*/
public class Item implements Serializable
{
private int itemId;
private String
itemName;
private Map<String,
String> images = new HashMap<String,
String>();
配置文件:
view
plaincopy
to clipboardprint?
<hibernate-mapping package="cn.partner4java.map">
<class name="Item">
<id
name="itemId">
<generator class="native"/>
</id>
<property
name="itemName" type="string"/>
<map
name="images" table="ITEM_IMAGES">
<key
column="ITEM_ID"></key>
<map-key
type="string" column="IMAGENAME"></map-key>
<element
type="string" column="FILENAME" not-null="true"/>
</map>
</class>
</hibernate-mapping>
插入:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().put("imagename1", "filename1");
item.getImages().put("imagename1", "filename1");
hibernate打印sql:
Hibernate: insert into Item (itemName) values (?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, IMAGENAME, FILENAME) values (?, ?, ?)
映射sortedmap,排序集合:
类:
view
plaincopy
to clipboardprint?
/**
*
映射sortedmap,排序集合
*/
public class Item implements Serializable
{
private int itemId;
private String
itemName;
private SortedMap<String,
String> images = new TreeMap<String,
String>();
配置文件:
view
plaincopy
to clipboardprint?
<hibernate-mapping package="cn.partner4java.sortedmap">
<class name="Item">
<id
name="itemId">
<generator class="native"/>
</id>
<property
name="itemName" type="string"/>
<!--
sort="natural"是按照string进行排序,也可实现java.util.Comparator
如:srot="cn.partner4java.MyComp" -->
<map
name="images" table="ITEM_IMAGES" sort="natural">
<key
column="ITEM_ID"></key>
<map-key
type="string" column="IMAGENAME"></map-key>
<element
type="string" column="FILENAME" not-null="true"/>
</map>
</class>
</hibernate-mapping>
插入:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().put("imagename2", "filename2");
item.getImages().put("imagename1", "filename1");
hibernate打印sql:
Hibernate: insert into Item (itemName) values (?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, IMAGENAME, FILENAME) values (?, ?, ?)
Hibernate: insert into ITEM_IMAGES (ITEM_ID, IMAGENAME, FILENAME) values (?, ?, ?)
(数据中,images1的插入顺序是按照string排序的,也就是先插入了imagename1)
order-by:
view
plaincopy
to clipboardprint?
<map
name="images" table="ITEM_IMAGES" order-by="">
<set
name="images" table="ITEM_IMAGES" order-by="FILENAME
asc">
order-by属性中的表达式是SQL order by 子句的一个片段,可以按集合表的任何列进行排序。
组件的集合
组件的集合被类似地映射到JDK值类型的集合。唯一的区别是用<composite-element>代替
<element>标签。
类:
view
plaincopy
to clipboardprint?
/**
*
映射集合
*/
public class Item implements Serializable
{
private int itemId;
private String
itemName;
private Set<ItemImage>
images = new HashSet<ItemImage>();
public class ItemImage implements Serializable
{
private String
imageName;
private String
fileName;
private int sizeX;
private int sizeY;
配置文件:
view
plaincopy
to clipboardprint?
<hibernate-mapping package="cn.partner4java.composite">
<class name="Item">
<!--
如果你不给它明确指定column="ITEM_ID",他是不会截取大写字母添加下划线的,不知道为什么,可能是现在的版本就这样了
-->
<id
name="itemId" column="ITEM_ID">
<generator class="native"/>
</id>
<property
name="itemName" type="string" column="ITEM_NAME"/>
<set
name="images" table="ITEM_IMAGE" order-by="IMAGE_NAME
asc">
<!--
是定义 ITEM_IMAGE 表,与主表关联的字段名称,和主表的id无任何关系,也就是这里可以随意写 -->
<key
column="ITEM_ID"></key>
<composite-element class="ItemImage">
<property
name="imageName" column="IMAGE_NAME" not-null="true"></property>
<property
name="fileName" column="FILE_NAME" not-null="true"></property>
<property
name="sizeX" column="SIZE_X" not-null="true"></property>
<property
name="sizeY" column="SIZE_Y" not-null="true"></property>
</composite-element>
</set>
</class>
</hibernate-mapping>
插入:
view
plaincopy
to clipboardprint?
Item
item = new Item();
item.setItemName("hello
world");
item.getImages().add(new ItemImage("imageName", "fileName", 1, 2));
hibernate打印sql:
Hibernate: insert into Item (ITEM_NAME) values (?)
Hibernate: insert into ITEM_IMAGE (ITEM_ID, IMAGE_NAME, FILE_NAME, SIZE_X, SIZE_Y) values (?, ?, ?, ?, ?)
用注解映射集合
基本的集合映射:
映射无序的set集合:
类:
view
plaincopy
to clipboardprint?
/**
*
基本的集合映射(映射无序的set集合)
*
@author partner4java
*
*/
@Entity
public class Item implements Serializable
{
@Id
@GeneratedValue
@Column(name="item_id")
private int itemId;
@Column(name="item_name",length=100)
private String
itemName;
//hibernate
annotation 包对包含值类型元素的集合映射支持非标准的注解,
//主要是CollectionOfElements
@CollectionOfElements(targetElement=java.lang.String.class)
//指定加入的表名,和加入表的对应列名
@JoinTable(name="ITEM_IMAGE",joinColumns=@JoinColumn(name="ITEM_ID"))
@Column(name="FILENAME",nullable=false)
private Set<String>
images = new HashSet<String>();
有序的list集合:
view
plaincopy
to clipboardprint?
/**
*
有序的list集合
*
@author partner4java
*
*/
@Entity
public class Item implements Serializable
{
@Id
@GeneratedValue
@Column(name="ITEM_ID")
private Integer
itemId;
@Column(name="ITEM_NAME",length=100)
private String
itemName;
@CollectionOfElements(targetElement=java.lang.String.class)
@JoinTable(name="ITEM_IMAGE",joinColumns=@JoinColumn(name="ITME_ID"))
//为了映射持久化list,需要添加
IndexColumn,该索引列默认基数为0
@IndexColumn(name="POSITION",base=1)
@Column(name="FILENAME")
private List<String>
images = new ArrayList<String>();
映射持久化的映射Map:
view
plaincopy
to clipboardprint?
/**
*
映射持久化的映射Map
*
@author partner4java
*
*/
@Entity
public class Item implements Serializable
{
@Id
@GeneratedValue
@Column(name="ITEM_ID")
private Integer
itemId;
@Column(name="ITEM_NAME",length=100)
private String
itemName;
@CollectionOfElements
@JoinTable(name="ITEM_IMAGE",joinColumns=@JoinColumn(name="ITEM_ID"))
@MapKey(columns=@Column(name="IMAGENAME"))
@Column(name="FILENAME")
private Map<String,
String> images = new HashMap<String,
String>();
排序集合:
view
plaincopy
to clipboardprint?
/**
*
排序集合
*
@author partner4java
*
*/
@Entity
public class Item implements Serializable
{
@Id
@GeneratedValue
@Column(name="ITEM_ID")
private Integer
itemId;
@Column(name="ITEM_NAME")
private String
itemName;
@CollectionOfElements
@JoinTable(name="ITEM_IMAGE",joinColumns=@JoinColumn(name="ITEM_ID"))
//排序
@Sort(type=SortType.NATURAL)
@Column(name="FILENAME")
private SortedSet<String>
images = new TreeSet<String>();
添加order by排序:
view
plaincopy
to clipboardprint?
/**
*
添加order by排序
*
@author partner4java
*
*/
@Entity
public class Item implements Serializable
{
@Id
@GeneratedValue
@Column(name="ITEM_ID")
private Integer
itemId;
@Column(name="ITEM_NAME")
private String
itemName;
@CollectionOfElements(targetElement=java.lang.String.class)
@JoinTable(name="ITEM_IMAGE",joinColumns=@JoinColumn(name="ITEM_ID"))
@Column(name="FILENAME")
//对有序列号的list类型是不起作用的
@OrderBy(clause="FILENAME
asc")
private Set<String>
images = new HashSet<String>();
映射父子关系
许多开发人员在开始使用hibernate时要尝试的第一件事就是父子关系的映射。
这通常是你第一次遇到集合,也是你第一次必须思考实体和值类型之间的区别,
否则会在ORM的复杂性中迷失。
下面简要的阐述了关系映射:
多样性:
在描述和分类关联时,我们通常使用术语多样性。在我们的例子中,多样性只是两小块信息:
一个特定的Item可以有不止一个Bid吗?
一个特定的Bid可以有不止一个Item吗?
看一眼领域模型之后,就可以推断:从Bid到Item的关联是一个多对一的关联。回忆一下,关联是有方向性的,
把从Item到Bid的方向关联归为一对多的关联。
另外只有两种可能:多对多和一对一。
在对象持久化的上下文中,我们不关注多个(many)是否意味着两个或者最大五个或者没有限制:只关注大多数
关联的选择性;不特别关心是否需要关联的实例,或者关联的另一侧是否可以为空。但是,这些是影响你在关系
数据库Schema中选择完整性规则和在SQL DDL中定义约束的重要方面。
最简单的可能关联:
从Bid到Item的关联(反之亦然)是一种最简单的可能实体关联的例子。两个类中有两个属性。一个是引用的集合,另一个是单个引用。
首先,这是Bid的Java类实现:
view
plaincopy
to clipboardprint?
public class Bid{
...
private Item
item;
...
}
接下来是这个关联的Hibernate映射:
view
plaincopy
to clipboardprint?
<class
name="Bid"
table="BID">
...
<many-to-one
name="item"
column="ITEM_ID"
class="Item"
not-null="true"/>
</class>
如果拿这个与本章前面的集合映射进行比较,会发现你用一个不同的元素<one-to-many>映射了集合内容。这表明集合没有包含值类型实例,
而是包含了对实体实例的引用。现在hibernate知道如何处理共享的引用和被关联对象的生命周期(他禁用了值类型实例的所有隐式依赖的
生命周期)。hibernate也知道用给集合的表语目标实体类被映射到的表相同--<set>映射不需要table属性。
由<key>元素定义的列映射的BID表的外键列ITEM_ID,即已经在关系的另一侧映射的同一个列。
注意,表Schema并没有改变:它与之前你的映射关联的多彻一样。但是,有一点不同:not null="true"不见了。问题是现在有两个不同的单项
关联映射到同一个外键列。
哪一侧控制这个列呢?
在运行时,同一个外键值有两个不同的内存表示法:Bid的item属性和由Item保存的bids集合的一个元素。假设应用程序修改了关联,例如通过
在addBid()方法的这个片段中对货品添加出价:
bid.setItem(item);
bids.add(bid);
在这种情况下hibernate侦测到内存持久化实例的两处变化。从数据库的观点来看,只有一个值必须更新以体现这些变化:BID表的ITEM_ID列。
hibernate没有透明地侦测到引用同一个数据库列的两处变化,因为此时还没有做任何事来表明这是一个双向的关联。换句话说,已经映射了
同一个列两次,hibernate始终需要知道这一点,因为它无法自动侦测到这个重复。
在关联映射中还需要做一件事情,就是是他成为真正的双向关联映射。inverse属性告诉hibernate,集合是<many-to-one>关联在另一侧的一个镜像:
也就是inverse一侧的改变不会引起数据库的改变,另一侧的改变才会引起数据库的改变。也就是把inverse标识在被维护的一端。
相关文章推荐
- hibernate 4 映射持久化类 | hibernate 实战(第二版) 第4章映射持久化类 | 笔记
- JavaPersistenceWithHibernate第二版笔记-第四章-Mapping persistent classes-003映射实体时的可选操作(<delimited-identifiers/>、PhysicalNamingStrategy、PhysicalNamingStrategyStandardImpl、、、)
- Hibernate实体映射笔记
- Hibernate高级实体关联映射之多值的实体关联(一对多关联,利用联结表,idbag例)
- hibernate 关联映射学习备忘笔记
- hibernate中一对多映射(set集合中存放的原生数据类型,而不是实体)
- Hibernate实战_笔记26(映射组件)
- Hibernate实体映射笔记
- Hibernate实体映射笔记
- hibernate中实体关联的注解写法(组件映射)
- hibernate实体及集合属性、关联实体的延迟加载
- hibernate笔记(八)一对一关联映射分析
- Hibernate学习笔记:集合映射之映射Map
- Hibernate实战_笔记32(考虑定制的映射类型、创建UserType)
- hibernate学习笔记-2入门初体验关联映射
- Hibernate实战_笔记23(映射持久化)
- Hibernate实体映射笔记
- JavaEE经典试题(八)Hibernate实体关联映射
- Hibernate视频学习笔记(4)多对一及一对一关联映射
- Hibernate 学习笔记07 --集合映射_&_继承映射