11.2、List映射
对于Collection子接口有两个常用的:无重复的set子接口、允许重复的List子接口,而且在List接口中大量的扩充了Collection接口里面的方法,而且List接口有一个get()方法,此方法可以根据索引取数据,所以List集合本身就具备了索引的能力。而马上要讲解的List映射也会包含索引与数据两个部分。
范例:数据库创建脚本
- 使用数据库 USE mldn ; -- 删除数据表 DROP TABLE books ; DROP TABLE member ; -- 创建数据表 CREATE TABLE member( mid VARCHAR(50) , name VARCHAR(50) , CONSTRAINT pk_mid PRIMARY KEY(mid) ) ; CREATE TABLE books( mid VARCHAR(50) , position INT , title VARCHAR(200) , CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES member(mid) ON DELETE CASCADE ) ; |
其中在Books表中定义的position字段,就表示一个数据的访问索引。下面就根据以上的脚本加入Hibernate支持。
范例:修改Member.java类的定义
package cn.cgj.pojo; import java.util.List; @SuppressWarnings("serial") public class Member implements java.io.Serializable { private String mid; private String name; private List books = new ArrayList(); public Member() { } //setter、getter略 } |
下面的关键还是在于Member.hbm.xml文件的修改上。
范例:修改Member.hbm.xml文件,加上List支持
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="cn.cgj.pojo.Member" table="member" catalog="mldn"> <id name="mid" type="java.lang.String"> <column name="mid" length="50" /> <generator class="assigned"></generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="50" /> </property> <list name="books" table="books" lazy="false"> <key> <column name="mid"/> </key> <index column="position"/> <element column="title" type="java.lang.String"/> </list> </class> </hibernate-mapping> |
范例:实现数据的增加操作
package cn.cgj.pojo; import cn.cgj.dbc.HibernateSessionFactory; public class MemberTestInsert { public static void main(String[] args) { Member mem = new Member(); mem.setMid("daguo" + System.currentTimeMillis()); mem.setName("大国"); mem.getBooks().add("java核心技术"); mem.getBooks().add("java核心技术"); mem.getBooks().add("java核心技术"); mem.getBooks().add("java开发实战经典"); mem.getBooks().add("java开发实战经典"); mem.getBooks().add("java开发实战经典"); mem.getBooks().add("java开发实战经典"); HibernateSessionFactory.getSession().save(mem); HibernateSessionFactory.getSession().beginTransaction().commit(); HibernateSessionFactory.closeSession(); } } |
Hibernate: insert into mldn.member (name, mid) values (?, ?) Hibernate: insert into books (mid, position, title) values (?, ?, ?) Hibernate: insert into books (mid, position, title) values (?, ?, ?) Hibernate: insert into books (mid, position, title) values (?, ?, ?) Hibernate: insert into books (mid, position, title) values (?, ?, ?) Hibernate: insert into books (mid, position, title) values (?, ?, ?) Hibernate: insert into books (mid, position, title) values (?, ?, ?) Hibernate: insert into books (mid, position, title) values (?, ?, ?) |
现在同样实现了两张表的增加操作。而后在books表中可以发现position列的内容会自动的进行增长。
范例:实现数据的查询
package cn.cgj.pojo; import cn.cgj.dbc.HibernateSessionFactory; public class MemberTestSelectById { public static void main(String[] args) { Member mem = (Member) HibernateSessionFactory.getSession().get(Member.class, "daguo1456907570242"); System.out.println(mem); HibernateSessionFactory.closeSession(); } } |
Hibernate: select member0_.mid as mid0_0_, member0_.name as name0_0_ from mldn.member member0_ where member0_.mid=? Hibernate: select books0_.mid as mid0_0_, books0_.title as title0_, books0_.position as position0_ from books books0_ where books0_.mid=? Member [mid=daguo1456907570242, name=大国, books=[java核心技术, java核心技术, java核心技术, java开发实战经典, java开发实战经典, java开发实战经典, java开发实战经典]] |
操作的形式上和set集合的区别不大,但是在数据的保存上还是存在一些细微的区别的,而对应的其他操作与set集合的操作类似。
11.3、Map映射
Map集合最大的特征就是存在key与value的对应关系,所以在进行数据保存的时候,子表之中也一定会存在两个字段,一个是key,一个是value。
范例:数据库创建脚本
-- 使用数据库 USE mldn ; -- 删除数据表 DROP TABLE grade ; DROP TABLE sporter ; -- 创建数据表 CREATE TABLE sporter( sid VARCHAR(50) , name VARCHAR(50) , sex VARCHAR(10) , CONSTRAINT pk_sid PRIMARY KEY(sid) ) ; CREATE TABLE grade( sid VARCHAR(50) , item VARCHAR(50) , mark INT , CONSTRAINT fk_sid FOREIGN KEY(sid) REFERENCES sporter(sid) ON DELETE CASCADE ) ; |
很明显,现在每一个项目都应该对应一个运动员的成绩,而且此处也不考虑项目的名称是否重复。之后创建Hibernate映射。
范例:修改sporter.java类
package cn.cgj.pojo; import java.util.HashMap; import java.util.Map; @SuppressWarnings("serial") public class Sporter implements java.io.Serializable {
private String sid; private String name; private String sex; private Map grades = new HashMap(); public Sporter() { } //setter、getter略 } |
范例:修改sporter.hbm.xml文件
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="cn.cgj.pojo.Sporter" table="sporter" catalog="mldn"> <id name="sid" type="java.lang.String"> <column name="sid" length="50" /> <generator class="assigned"></generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="50" /> </property> <property name="sex" type="java.lang.String"> <column name="sex" length="10" /> </property> <map name="grades" table="grade" lazy="false"> <key> <column name="sid"/> </key> <map-key type="java.lang.String" column="item"/> <element type="int" column="mark"/> </map> </class> </hibernate-mapping>
|
范例:测试增加
package cn.cgj.test; import cn.cgj.dbc.HibernateSessionFactory; import cn.cgj.pojo.Sporter; public class SporterTestInsert { public static void main(String[] args) { Sporter sporter = new Sporter(); sporter.setSid("daguo"); sporter.setName("大国"); sporter.setSex("男"); sporter.getGrades().put("跳高", 11); sporter.getGrades().put("跳水", 1); sporter.getGrades().put("跳远", 21); HibernateSessionFactory.getSession().save(sporter); HibernateSessionFactory.getSession().beginTransaction().commit(); HibernateSessionFactory.closeSession(); } } |
Hibernate: insert into mldn.sporter (name, sex, sid) values (?, ?, ?) Hibernate: insert into grade (sid, item, mark) values (?, ?, ?) Hibernate: insert into grade (sid, item, mark) values (?, ?, ?) Hibernate: insert into grade (sid, item, mark) values (?, ?, ?) |
范例:查询数据
package cn.cgj.test; import cn.cgj.dbc.HibernateSessionFactory; import cn.cgj.pojo.Sporter; public class SporterTestSelectById { public static void main(String[] args) { Sporter sporter = (Sporter) HibernateSessionFactory.getSession().get(Sporter.class, "daguo"); System.out.println(sporter); HibernateSessionFactory.closeSession(); } } |
Hibernate: select sporter0_.sid as sid0_0_, sporter0_.name as name0_0_, sporter0_.sex as sex0_0_ from mldn.sporter sporter0_ where sporter0_.sid=? Hibernate: select grades0_.sid as sid0_0_, grades0_.mark as mark0_, grades0_.item as item0_ from grade grades0_ where grades0_.sid=? Sporter [sid=daguo, name=大国, sex=男, grades={跳远=21, 跳高=11, 跳水=1}] |
此时也是发出了两条指令,这样的好处明显就避免了多表查询的性能问题,但是通过以上三种映射可以发现:
l Set映射只适合与子表中存在有一个字段(不包含外键)的情况下使用。
l List映射适合于子表中有一个字段(不包含外键),但是可以重复,区分是依靠索引列来完成。
l Map映射包含两个字段(不包含外键),key和value的内容可以由用户自己设置。
11.4、Array映射
这种映射采用的是数组的方式进行的保存,数组也就相当于集合,只不过此处是直接使用的数组完成的。
范例:数据库的创建脚本
-- 使用数据库 USE mldn ; -- 删除表 DROP TABLE message ; DROP TABLE member ; -- 创建表 CREATE TABLE member( mid VARCHAR(50) , name VARCHAR(50) , CONSTRAINT pk_mid PRIMARY KEY(mid) ) ; CREATE TABLE message( mid VARCHAR(50) , ind INT , content TEXT , CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES member(mid) ON DELETE CASCADE ) ; |
可以感觉到此时的数组的映射结构和List非常相似,一定也需要一个索引的列,随后为项目增加Hibernate支持。
范例:修改Member.java类定义
package cn.cgj.pojo; public class Member implements java.io.Serializable { private String mid; private String name; private String [] messages ; public Member() { } //setter、getter略 } |
范例:修改Member.hbm.xml文件
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="cn.cgj.pojo.Member" table="member" catalog="mldn"> <id name="mid" type="java.lang.String"> <column name="mid" length="50" /> <generator class="assigned"></generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="50" /> </property> <array name="messages" table="message" > <key> <column name="mid"/> </key> <list-index column="ind"/> <element type="java.lang.String" column="content"/> </array> </class> </hibernate-mapping>
|
与List映射的不同在于,List使用的是index,而数组使用的是List_index。
范例:测试增加数据
package cn.cgj.test; import cn.cgj.dbc.HibernateSessionFactory; import cn.cgj.pojo.Member; public class MemberTestInsert { public static void main(String[] args) { Member member = new Member() ; member.setMid("mldn - " + System.currentTimeMillis()); member.setName("李兴华"); member.setMessages(new String[]{ "魔乐科技软件学院在北京" , "后续的图书为Java Web开发实战经典(框架篇)", "后续的图书为Java Web开发实战经典(前台技术篇)" }); HibernateSessionFactory.getSession().save(member) ; HibernateSessionFactory.getSession().beginTransaction().commit(); HibernateSessionFactory.closeSession(); } } |
insert into mldn.member (name, mid) values (?, ?) Hibernate: insert into message (mid, ind, content) values (?, ?, ?) Hibernate: insert into message (mid, ind, content) values (?, ?, ?) Hibernate: insert into message (mid, ind, content) values (?, ?, ?) |
这个时候的索引依然是采用自动编号的方式完成。
范例:查询数据
package cn.cgj.test; import cn.cgj.dbc.HibernateSessionFactory; import cn.cgj.pojo.Member; public class MemberTestSelectById { public static void main(String[] args) { Member member = (Member) HibernateSessionFactory.getSession().get(Member.class, "mldn - 1456915152014"); System.out.println(member); HibernateSessionFactory.closeSession(); } } |
Hibernate: select member0_.mid as mid0_0_, member0_.name as name0_0_ from mldn.member member0_ where member0_.mid=? Hibernate: select messages0_.mid as mid0_0_, messages0_.content as content0_, messages0_.ind as ind0_ from message messages0_ where messages0_.mid=? Member [mid=mldn - 1456915152014, name=李兴华, messages=[魔乐科技软件学院在北京, 后续的图书为Java Web开发实战经典(框架篇), 后续的图书为Java Web开发实战经典(前台技术篇)]] |
但是从使用上来讲,如果非要使用数组,还是建议换成List集合更好,因为数组最大的缺点在于长度固定。
11.5、Bag映射
Bag实际上就是一种没有索引列的List映射。简化了的映射操作。
范例:数据库创建脚本
-- 使用数据库 USE mldn ; -- 删除数据表 DROP TABLE books ; DROP TABLE member ; -- 创建数据表 CREATE TABLE member( mid VARCHAR(50) , name VARCHAR(50) , CONSTRAINT pk_mid PRIMARY KEY(mid) ) ; CREATE TABLE books( mid VARCHAR(50) , title VARCHAR(200) , CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES member(mid) ON DELETE CASCADE ) ; |
为项目添加Hibernate支持,同时还需要手工进行代码的修改。
范例:修改Member.java类
package cn.cgj.pojo; import java.util.ArrayList; import java.util.List; public class Member implements java.io.Serializable { private String mid; private String name; private List bookses = new ArrayList(0); public Member() { } // setter、getter略 } |
范例:编写Member.hbm.xml文件
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="cn.cgj.pojo.Member" table="member" catalog="mldn"> <id name="mid" type="java.lang.String"> <column name="mid" length="50" /> <generator class="assigned"></generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="50" /> </property> <bag name="bookses" table="books" lazy="false"> <key> <column name="mid"/> </key> <element type="java.lang.String" column="title"/> </bag> </class> </hibernate-mapping> |
范例:实现数据的增加操作
package cn.cgj.test; import cn.cgj.dbc.HibernateSessionFactory; import cn.cgj.pojo.Member; public class MemberTestInsert { public static void main(String[] args) { Member member = new Member(); member.setMid("daguo"); member.setName("大国"); member.getBookses().add("javaWeb开发"); member.getBookses().add("javaWeb开发"); member.getBookses().add("javaWeb开发"); member.getBookses().add("javaweb基础"); member.getBookses().add("javaweb基础"); member.getBookses().add("javaweb基础"); HibernateSessionFactory.getSession().save(member); HibernateSessionFactory.getSession().beginTransaction().commit(); HibernateSessionFactory.closeSession();
} } |
Hibernate: insert into mldn.member (name, mid) values (?, ?) Hibernate: insert into books (mid, title) values (?, ?) Hibernate: insert into books (mid, title) values (?, ?) Hibernate: insert into books (mid, title) values (?, ?) Hibernate: insert into books (mid, title) values (?, ?) Hibernate: insert into books (mid, title) values (?, ?) Hibernate: insert into books (mid, title) values (?, ?) |
范例:实现数据的查询操作
package cn.cgj.test; import cn.cgj.dbc.HibernateSessionFactory; import cn.cgj.pojo.Member;
public class MemberTestSelectById { public static void main(String[] args) { Member member = (Member) HibernateSessionFactory.getSession().get(Member.class, "daguo"); System.out.println(member); HibernateSessionFactory.closeSession();
} } |
Hibernate: select member0_.mid as mid0_0_, member0_.name as name0_0_ from mldn.member member0_ where member0_.mid=? Hibernate: select bookses0_.mid as mid0_0_, bookses0_.title as title0_ from books bookses0_ where bookses0_.mid=? Member [mid=daguo, name=大国, bookses=[javaWeb开发, javaWeb开发, javaWeb开发, javaweb基础, javaweb基础, javaweb基础]] |
此时也同样发出了两个查询指令,而且现在也不需要一个索引列的标记了。
总结:
1、 重点的映射在于三种:Set、List、Map三种;
在一些老的项目之中会使用Set映射来解决多对多关系表的数据维护情况。