容器映射

容器映射完成pojo对象中出现的集合属性的映射
但与Java的一对多关系不同,这个集合属性中只能保存数据库中支持的基本类型(String,int,double,date)

由于属性为集合类型,有以下三种配置形式:
1、 Set
2、 List
3、 Map

一、Set集合
完成一个人和邮件地址的关系。
设计表:
人:userid,name,age,birthday
邮件地址表: userid、email,使用复合主键

使用容器映射的前提:
多的一方的表只能包含两个字段,并且为复合主键,其中一个字段为一的一方的外键,另一个为基本的数据类型,而在编写的pojo类中,集合中保存的数据,应该为多的一方表中另一个字段的基本类型。

所有对地址的操作都由人来完成,只建立一个 pojo类(人的类),为该类加入一个Set集合属性,该属性中保存了所有该人的邮件地址。

1、建立表
DROP TABLE user ;

DROP TABLE email ;

CREATE TABLE user (
userid varchar(18) primary key ,
name varchar(20) not null,
age int not null,
birthday date not null
);

CREATE TABLE email (
userid varchar(18) not null,
email varchar(50) not null,
primary key (userid,email)
);

2、生成映射
生成映射,只生成user的映射类。
在pojo中加入一个Set集合,该集合的泛型为String类型

package org.liky.pojo;

import java.util.Date;
import java.util.Set;
import java.util.TreeSet;

/**
* User generated by MyEclipse Persistence Tools
*/

public class User implements java.io.Serializable {

// Fields

private String userid;

private String name;

private Integer age;

private Date birthday;

private Set<String> emails = new TreeSet<String>();

// Constructors

/** default constructor */
public User() {
}

/** full constructor */
public User(String userid, String name, Integer age, Date birthday) {
this.userid = userid;
this.name = name;
this.age = age;
this.birthday = birthday;
}

// Property accessors

public String getUserid() {
return this.userid;
}

public void setUserid(String userid) {
this.userid = userid;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return this.age;
}

public void setAge(Integer age) {
this.age = age;
}

public Date getBirthday() {
return this.birthday;
}

public void setBirthday(Date birthday) {
this.birthday = birthday;
}

public Set<String> getEmails() {
return emails;
}

public void setEmails(Set<String> emails) {
this.emails = emails;
}

}


3、修改映射文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.liky.pojo.User" table="user" catalog="testdb">
<id name="userid" type="java.lang.String">
<column name="userid" length="18" />
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="20" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" not-null="true" />
</property>
<property name="birthday" type="java.util.Date">
<column name="birthday" length="10" not-null="true" />
</property>
<!-- 表示User中包含一个Set类型的属性,在该集合中保存的数据与email表有关系 -->
<set name="emails" table="email">
<!-- 在表email中通过userid与user表关联 -->
<key column="userid"></key>
<!-- 表示Set集合中保存的数据类型,和该数据所对应的表的字段,这里集合中所保存的数据对应表中的email列 -->
<element type="java.lang.String" column="email"></element>
</set>
</class>
</hibernate-mapping>

4、编写后台代码

5、测试
// 插入一个User,同时将该User的Email也插入
User user = new User();
user.setUserid("123456789123456789");
user.setName("MLDN");
user.setAge(33);
user.setBirthday(new Date());

user.getEmails().add("mldnqa@163.com");
user.getEmails().add("mldnkf@163.com");
user.getEmails().add("lxh@mldn.cn");
user.getEmails().add("lq@mldn.cn");

// 保存数据
try {
userdao.doCreate(user);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


6、LazyInitializationException异常
完成修改:
先查询某个用户的全部邮件地址,列表显示
在显示邮件地址时,会出现以下异常

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.liky.pojo.User.emails, no session or session was closed
该异常为延迟加载异常,在Hibernate使用过程中非常常见。

产生原因:
在Hibernate中,多表关联查询时,为了提高查询性能,设置了一个延迟加载机制(懒汉式)
也就是说,当用到另一个表的数据时,再去数据库中查询该表的数据。
但是这个查询还需要使用之前查询所使用的连接。

这里出现异常的原因是由于在执行了User的查询后,就将连接关闭了,再调用email查询时,无法找到之前打开的连接,因此出现了异常。

解决方法:
解决方法:
1、 不关闭Session连接(个人不推荐)
在代理类中不关闭连接
public User findById(String id) throws Exception {
// TODO Auto-generated method stub
User test = null;
try {
test =this.testdao.findById(id);
} catch (RuntimeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {

}

return test;
}

2、修改延迟加载设置,不使用lazy
修改映射文件,为set加入一个lazy属性
<set name="emails" table="email" lazy="false">
这样使用不灵活,有时需要懒汉模式,有时不需要,而这样全部取消,也不好

3、在关闭前先查询出所要查询的内容
修改代理类中的内容,完成在关闭前的查询操作
public User findById(String id) throws Exception {
// TODO Auto-generated method stub
User test = null;
try {
test =this.testdao.findById(id);
test.getEmails().size();
} catch (RuntimeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
this.instance.close();
}
return test;
}

7、完成只删除和修改Email的功能

要完成该功能,需要调用user的修改方法,而且只能使用session.update的修改方法。

补充:
两种修改与删除方法的最后一个区别:
Session方式的会同时对关联表起作用,而使用HQL无法影响到对方表
当数据库包含外键关系时,可以直接使用HQL进行删除,数据库会自动完成级联删除功能。
而如果不包含外键,则只能使用session.delete进行级联删除功能。
二、List集合

list:映射,可以允许重复,而且可以依据下标直接取得对象。
list映射和set映射的区别在于是否允许数据重复。
在表的设计上有区别
list方式映射时,表中包含三个字段,多一个下标的字段,用来区分内容相同的数据。
主键改为3主键

1、建立表
DROP TABLE user ;

DROP TABLE email ;

CREATE TABLE user (
userid varchar(18) primary key ,
name varchar(20) not null,
age int not null,
birthday date not null
);

CREATE TABLE email (
userid varchar(18) not null,
email varchar(50) not null,
indexid int not null,
primary key (userid,email,indexid)
);

2、生成映射
修改pojo类加入List集合
package org.liky.pojo;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* User generated by MyEclipse Persistence Tools
*/

public class User implements java.io.Serializable {

// Fields

private String userid;

private String name;

private Integer age;

private Date birthday;

private List<String> emails = new ArrayList<String>();

// Constructors

/** default constructor */
public User() {
}

/** full constructor */
public User(String userid, String name, Integer age, Date birthday) {
this.userid = userid;
this.name = name;
this.age = age;
this.birthday = birthday;
}

// Property accessors

public String getUserid() {
return this.userid;
}

public void setUserid(String userid) {
this.userid = userid;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return this.age;
}

public void setAge(Integer age) {
this.age = age;
}

public Date getBirthday() {
return this.birthday;
}

public void setBirthday(Date birthday) {
this.birthday = birthday;
}

public List<String> getEmails() {
return emails;
}

public void setEmails(List<String> emails) {
this.emails = emails;
}

}

3、修改映射文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.liky.pojo.User" table="user" catalog="testdb">
<id name="userid" type="java.lang.String">
<column name="userid" length="18" />
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="20" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" not-null="true" />
</property>
<property name="birthday" type="java.util.Date">
<column name="birthday" length="10" not-null="true" />
</property>
<!-- 表示User中包含一个List类型的属性,在该集合中保存的数据与email表有关系 -->
<list name="emails" table="email">
<!-- 在表email中通过userid与user表关联 -->
<key column="userid"></key>
<!-- 需要包含一个索引号,表示indexid为索引列,类型为Integer -->
<index column="indexid" type="java.lang.Integer"></index>
<!-- 表示List集合中保存的数据类型,和该数据所对应的表的字段,这里集合中所保存的数据对应表中的email列 -->
<element type="java.lang.String" column="email"></element>
</list>
</class>
</hibernate-mapping>
其他操作参考Set


三、Map集合
Map:使用key与value的形式保存数据。
表需要修改,改为3个字段,修改为key与value的形式

1、建立表
DROP TABLE user ;

DROP TABLE email ;

CREATE TABLE user (
userid varchar(18) primary key ,
name varchar(20) not null,
age int not null,
birthday date not null
);

CREATE TABLE email (
userid varchar(18) not null,
email varchar(50) not null,
keyss varchar(20) not null,
primary key (userid,email,keyss)
);

2、修改pojo对象
package org.liky.pojo;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
* User generated by MyEclipse Persistence Tools
*/

public class User implements java.io.Serializable {

// Fields

private String userid;

private String name;

private Integer age;

private Date birthday;

private Map<String, String> emails = new TreeMap<String, String>();

// Constructors

/** default constructor */
public User() {
}

/** full constructor */
public User(String userid, String name, Integer age, Date birthday) {
this.userid = userid;
this.name = name;
this.age = age;
this.birthday = birthday;
}

// Property accessors

public String getUserid() {
return this.userid;
}

public void setUserid(String userid) {
this.userid = userid;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return this.age;
}

public void setAge(Integer age) {
this.age = age;
}

public Date getBirthday() {
return this.birthday;
}

public void setBirthday(Date birthday) {
this.birthday = birthday;
}

public Map<String, String> getEmails() {
return emails;
}

public void setEmails(Map<String, String> emails) {
this.emails = emails;
}

}

3、修改映射文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.liky.pojo.User" table="user" catalog="testdb">
<id name="userid" type="java.lang.String">
<column name="userid" length="18" />
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="20" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" not-null="true" />
</property>
<property name="birthday" type="java.util.Date">
<column name="birthday" length="10" not-null="true" />
</property>
<map name="emails" table="email">
<key column="userid"></key>
<index column="keyss" type="java.lang.String"></index>
<element type="java.lang.String" column="email"></element>
</map>
</class>
</hibernate-mapping>


其他操作参考Set
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值