Map集合映射分为值类型映射和实体类型映射。
一、值类型映射
POJO类如下。
public class Product {
private Integer id;
private String name;
private Map images;//该实体类的该属性对应的类是java.util.Map,对应于Hibernate中的<map>映射
......
}
其映射文件如下。
<hibernate-mapping package="org.louis.domain">
<class name="Product" table="TEST_PRODUCT">
<id name="id" column="ID">
<generator class="native"></generator>
</id>
<property name="name" column="NAME"></property>
<map name="images" table="TEST_IMAGES"><!-- 映射map的名称为images,对应的表名是TEST_IMAGES -->
<key column="product_id"></key><!-- 表明 TEST_IMAGES表的外键是product_id,并且与TEST_PRODUCT表的主键关联-->
<index column="image_name" type="string"></index><!-- 指明map中的key -->
<element column="image_file" type="string"></element><!-- 值类型都是用element映射。此处指明map中的value,一个map节点只能有一个element节点 -->
</map>
</class>
</hibernate-mapping>
先解释一下映射文件中的<map>元素(看注释)。
下面进行测试。
1、插入数据
public void insert() {
Session session = HibernateSessionFactory.getSessionFactory()
.getCurrentSession();
session.beginTransaction();
Product p = new Product();
p.setName("p1");
Map m = new HashMap();
for (int i = 1; i < 6; i++) {
m.put("image" + i, "image" + i + ".jpg");
}
p.setImages(m);
session.save(p);
session.getTransaction().commit();
}
执行这段代码后台的SQL如下:
Hibernate:
insert
into
TEST_PRODUCT
(NAME)
values
(?)
Hibernate:
insert
into
TEST_IMAGES
(product_id, image_name, image_file)
values
(?, ?, ?)
Hibernate:
insert
into
TEST_IMAGES
(product_id, image_name, image_file)
values
(?, ?, ?)
Hibernate:
insert
into
TEST_IMAGES
(product_id, image_name, image_file)
values
(?, ?, ?)
Hibernate:
insert
into
TEST_IMAGES
(product_id, image_name, image_file)
values
(?, ?, ?)
Hibernate:
insert
into
TEST_IMAGES
(product_id, image_name, image_file)
values
(?, ?, ?)
可以看出向TEST_PRODUCT表中插入了一条数据,向TEST_IMAGES表中插入了5条数据。
2、加载数据
public void getProductById(Integer id) {
Session session = HibernateSessionFactory.getSessionFactory()
.getCurrentSession();
session.beginTransaction();
Product p = (Product) session.get(Product.class, id);
session.getTransaction().commit();
System.out.println("产品图片:");
for (Iterator iter = p.getImages().keySet().iterator(); iter.hasNext();) {
String key = (String) iter.next();
System.out.println(key + " : " + p.getImages().get(key));
}
}
执行这段代码后台如下:
Hibernate:
select
product0_.ID as ID8_1_,
product0_.NAME as NAME8_1_
from
TEST_PRODUCT product0_
where
product0_.ID=?
产品图片:
Hibernate:
select
images0_.product_id as product1_0_,
images0_.image_file as image2_0_,
images0_.image_name as image3_0_
from
TEST_IMAGES images0_
where
images0_.product_id=?
image2 : image2.jpg
image1 : image1.jpg
image4 : image4.jpg
image3 : image3.jpg
image5 : image5.jpg
这个例子中的Map比较简单,key-value对中的value只是简单的一个字符串而已,但是如果value是个对象或者value由好几个字段组成呢?这种情况下,刚才的方式就不能满足要求了,这时候要使用<composite-element>节点来进行,如下。
<map name="images" table="TEST_IMAGES"><!-- 映射map的名称为images,对应的表名是TEST_IMAGES -->
<key column="product_id"></key><!-- 表明 TEST_IMAGES表的外键是product_id,并且与TEST_PRODUCT表的主键关联-->
<index column="image_name" type="string"></index><!-- 指明map中的key -->
<composite-element class="Image">
<property name="imageName" column="image_name_"></property>
<property name="imageFile" column="image_file"></property>
<property name="imageSize" column="image_size"></property>
<property name="imageCreateTime" column="image_createTime"></property>
<property name="imageDesc" column="image_desc"></property>
</composite-element>
</map>
同时定义一个Image的POJO,这里就略去了,它的各个属性就是<property>中的name值。
运行下面的代码:
public void insert() {
Session session = HibernateSessionFactory.getSessionFactory()
.getCurrentSession();
session.beginTransaction();
Product p = new Product();
p.setName("p1");
Map m = new HashMap();
for (int i = 1; i < 6; i++) {
Image image = new Image();
image.setImageName("image" + i);
image.setImageFile("image" + i + ".jpg");
image.setImageDesc("image" + i + " desc");
image.setImageSize(1243);
image.setImageCreateTime(new Date());
m.put(image.getImageName(), image);
}
p.setImages(m);
session.save(p);
session.getTransaction().commit();
}
查看后台的SQL语句输出:
Hibernate:
insert
into
TEST_PRODUCT
(NAME)
values
(?)
Hibernate:
insert
into
TEST_IMAGES
(product_id, image_name, image_name_, image_file, image_size, image_createTime, image_desc)
values
(?, ?, ?, ?, ?, ?, ?)
Hibernate:
insert
into
TEST_IMAGES
(product_id, image_name, image_name_, image_file, image_size, image_createTime, image_desc)
values
(?, ?, ?, ?, ?, ?, ?)
Hibernate:
insert
into
TEST_IMAGES
(product_id, image_name, image_name_, image_file, image_size, image_createTime, image_desc)
values
(?, ?, ?, ?, ?, ?, ?)
Hibernate:
insert
into
TEST_IMAGES
(product_id, image_name, image_name_, image_file, image_size, image_createTime, image_desc)
values
(?, ?, ?, ?, ?, ?, ?)
Hibernate:
insert
into
TEST_IMAGES
(product_id, image_name, image_name_, image_file, image_size, image_createTime, image_desc)
values
(?, ?, ?, ?, ?, ?, ?)
二、映射实体类型
在映射值类型中,值类型是没有生命周期的,它随着Product的消亡而消亡。而现实中大多数类型是有生命周期的,这时就需要使用实体类型来映射了。
使用到得两个POJO是Prodcut和Image。这两个类都不用再做任何变化,只需要添加Image.hbm.mxl文件,并修改Product.hbm.xml二文件即可,结果如下:
<map name="images" cascade="all">
<key column="product_id"></key>
<index column="image_name" type="string"></index><!-- map中的键必须要指定类型 -->
<one-to-many class="Image"/>
</map>
这是Product.hbm.xml中修改的部分。
<hibernate-mapping package="org.louis.domain">
<class name="Image" table="TEST_IMAGE">
<id name="id" column="ID">
<generator class="native"></generator>
</id>
<property name="imageCreateTime" type="timestamp"></property>
<property name="imageDesc"></property>
<property name="imageFile"></property>
<property name="imageName" column="image_name"></property>
<property name="imageSize"></property>
</class>
</hibernate-mapping>
同样不用修改上面的测试代码,直接运行即可,下面是后台的SQL输出:
Hibernate:
insert
into
TEST_PRODUCT
(NAME)
values
(?)
Hibernate:
insert
into
TEST_IMAGE
(imageCreateTime, imageDesc, imageFile, image_name, imageSize)
values
(?, ?, ?, ?, ?)
Hibernate:
insert
into
TEST_IMAGE
(imageCreateTime, imageDesc, imageFile, image_name, imageSize)
values
(?, ?, ?, ?, ?)
Hibernate:
insert
into
TEST_IMAGE
(imageCreateTime, imageDesc, imageFile, image_name, imageSize)
values
(?, ?, ?, ?, ?)
Hibernate:
insert
into
TEST_IMAGE
(imageCreateTime, imageDesc, imageFile, image_name, imageSize)
values
(?, ?, ?, ?, ?)
Hibernate:
insert
into
TEST_IMAGE
(imageCreateTime, imageDesc, imageFile, image_name, imageSize)
values
(?, ?, ?, ?, ?)
Hibernate:
update
TEST_IMAGE
set
product_id=?,
image_name=?
where
ID=?
Hibernate:
update
TEST_IMAGE
set
product_id=?,
image_name=?
where
ID=?
Hibernate:
update
TEST_IMAGE
set
product_id=?,
image_name=?
where
ID=?
Hibernate:
update
TEST_IMAGE
set
product_id=?,
image_name=?
where
ID=?
Hibernate:
update
TEST_IMAGE
set
product_id=?,
image_name=?
where
ID=?
可以看到进行了插入操作,可能你要问了,为什么还有更新操作呢?其实这是因为<map>中默认的主控方是Product,如果你要是香闺这方面有更多了解的话看以参考我的另一篇文章---Hibernate的一对多和多对一关联关系