Hibernate高级映射 --- 组件映射
一 概念
1.组件映射概念
Hibernate建议在进行领域模型建模时要细粒度一些,简单的说,就是类要比表多,这种映射就是组件映射
组件类是值类型的,即它没有对象标识符属性,在数据库中也没有对应的表,它只隶书于另一个持久化类的实例。它的数据被嵌入到所隶书的持久化实例对应的数据库表的记录中。
2.组件映射的应用有三种常见的情况:
(1)把组件类作为持久化类的单个属性来使用
(2)把组件类作为持久化类的集合属性来使用
(3)把组件类作为持久化类的对象标识符来使用
3.组件类的作用
如果在User的实体类中有一个Name实体类,如果要想把Name的实体类放到User的表中,成为一张表,要用到组件映射。
二 代码分析 以User和Name为例
第一种:把组件类作为持久化类的单个属性来使用
1.建Name表 用来设置Name类中的属性
package com.hbsi.domain;
public class Name {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
2.建User表
package com.hbsi.domain;
import java.util.Date;
public class User {
private int id;
private Name name;//实体类
private Date birthday;
public User() {
super();
// TODO Auto-generatedconstructor stub
}
public User(int id, Namename, Date birthday) {
super();
this.id = id;
this.name = name;
this.birthday = birthday;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public NamegetName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
3.映射文件中增加Name类的组件映射
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hbsi.domain">
<class name="User" table="user">
<id name="id" column="id">
<generator class="native"/>
</id>
<!-- 组件映射 ,在User中有一个Name类 -->
<component name="name">
<property name="firstName"column="first_name"></property>
<property name="lastName"column="last_name"></property>
</component>
<property name="birthday" />
</class>
</hibernate-mapping>
注意:所用的标签是<component></component>
第二种:把组件类作为持久化类的集合属性来使用
1. 创建Photo实例类 为组件类的集合属性
package com.hbsi.domain;
public class Photo {
private String name;
private String filePath;
private String description;
public Photo() {
super();
// TODO Auto-generatedconstructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
2. 创建Album类
package com.hbsi.domain;
import java.util.List;
public class Album {
private Integer id;
private String title;
private String description;
private List<Photo> photos;
public Album() {
super();
// TODO Auto-generatedconstructor stub
}
public IntegergetId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Photo> getPhotos() {
return photos;
}
public void setPhotos(List<Photo> photos) {
this.photos = photos;
}
}
3.Album的映射文件
<?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.hbsi.domain">
<class name="Album" table="album">
<id name="id"column="id">
<generator class="native"/>
</id>
<property name="title"/>
<property name="description"/>
<!-- 用bag来映射list集合 -->
<bag name="photos"table="photo">
<key column="album_id"not-null="true"></key>
<!-- composite合成的意思 即为合成的元素 -->
<composite-element class="Photo">
<property name="name"></property>
<property name="filePath"></property>
<property name="description"></property>
</composite-element>
</bag>
</class>
</hibernate-mapping>
4.持久化类
package com.hbsi.test;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.hbsi.domain.Album;
importcom.hbsi.domain.Photo;
import com.hbsi.hibernate.utils.HibernateUtil;
public class PhotoAlbum {
publicstatic void main(String[] args) {
add();
}
staticvoid add() {
Session session = null;
Transaction transaction = null;
try {
session= HibernateUtil.getSession();
transaction= session.beginTransaction();
Albumalbum = new Album();
album.setTitle("熊熊的亮相");
album.setDescription("老王就是熊熊");
Photophoto = new Photo();
photo.setName("熊熊纪念册");
photo.setFilePath("老王宾馆");
photo.setDescription("熊熊是非常可爱的");
List<Photo>photos = new ArrayList<Photo>();
photos.add(photo);
album.setPhotos(photos);
session.save(album);
transaction.commit();
}finally {
if(session != null) {
session.close();
}
}
}
}
非常提醒:在测试的时候,实例化Album类和Photo类,在插入数据库的时候只插入album即可,而对于photo根本不用保存,因为photo只属于Album类中的一个属性类,没有id等约束,它它只属于一个类的分支,只能通过Album去控制,而不可以单独拿photo来操作,这个问题纠结了我半天啊!