用Hibernate已经有一段时间了,觉得关键还是设计对象时与数据库的映射策略最为关键。故而将已前写的笔记再翻出来看了看,今天将其记录在这里(好久都没来这写东西了,近来项目超得紧)
Hibernate Mapping笔记
一、List属性映射
数据库中有两个表,user和school表示一个用户所对应的学历信息,表结构下所示
用户表:
CREATE TABLE `user` ( `uid` int(11) NOT NULL AUTO_INCREMENT, `uname` varchar(32) DEFAULT NULL, `upassword` varchar(32) DEFAULT NULL, `usex` int(11) DEFAULT NULL, `uage` datetime DEFAULT NULL, PRIMARY KEY (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
学历表:
CREATE TABLE `school` ( `uid` int(11) NOT NULL, `sname` varchar(255) DEFAULT NULL, `list_order` int(11) NOT NULL, PRIMARY KEY (`uid`,`list_order`), KEY `FKC9E15B74B3DCEEC2` (`uid`), CONSTRAINT `FKC9E15B74B3DCEEC2` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
其中学历表school在对象模型中用List来表示,所以在Hibernate对象模型映射中为user设计user.java PO类,代码如下:
public class User implements java.io.Serializable { private Integer uid; private String uname; private String upassword; private Integer usex; private Date uage; private List school = new ArrayList(); public User() { } ........... } |
User.hbm.xml映射文件如下:
<?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">
<hibernate-mapping> <class name="com.gxd.list.po.User" table="user"> <id name="uid" type="integer"> <column name="uid" /> <generator class="native" /> </id> <property name="uname" type="string"> <column name="uname" length="32" /> </property> <property name="upassword" type="string"> <column name="upassword" length="32" /> </property> <property name="usex" type="integer"> <column name="usex" /> </property> <property name="uage" type="timestamp"> <column name="uage" length="0" /> </property> <!-- 映射集合属性,指定存放集合属性的表名 --> <list name="school" table="school"> <!-- 集合属性的持久化类的关联外键 --> <key column="uid" not-null="true"></key> <!-- 集合属性的次序列 --> <index column="list_order"></index> <!-- 集合属性的元素 --> <element type="string" column="sname"></element> </list> </class> </hibernate-mapping> |
测试类代码如下:
public static void main(String[] args) { Operator op = new Operator() ; User user = new User(); user.setUname("east"); user.setUpassword("123"); user.setUsex(1); user.setUage(new Date()); List<String> l = new ArrayList<String>(); l.add("沙田完小"); l.add("沙田中学"); l.add("武汉大学"); user.setSchool(l); op.addUser(user);
user = new User(); user.setUname("lili"); user.setUpassword("456"); user.setUsex(2); user.setUage(new Date()); l = new ArrayList<String>(); l.add("贝溪小学"); l.add("桂东二中"); l.add("湖南大学"); l.add("哈佛大学"); l.add("剑桥大学MBA"); user.setSchool(l); op.addUser(user); }
public void addUser(User user) { session.save(user); session.beginTransaction().commit(); } |
控制台执行结果:
Hibernate: insert into user (uname, upassword, usex, uage) values (?, ?, ?, ?) Hibernate: insert into school (uid, list_order, sname) values (?, ?, ?) Hibernate: insert into school (uid, list_order, sname) values (?, ?, ?) Hibernate: insert into school (uid, list_order, sname) values (?, ?, ?) Hibernate: insert into user (uname, upassword, usex, uage) values (?, ?, ?, ?) Hibernate: insert into school (uid, list_order, sname) values (?, ?, ?) Hibernate: insert into school (uid, list_order, sname) values (?, ?, ?) Hibernate: insert into school (uid, list_order, sname) values (?, ?, ?) Hibernate: insert into school (uid, list_order, sname) values (?, ?, ?) Hibernate: insert into school (uid, list_order, sname) values (?, ?, ?) |
表结果:
主键情况:
发现uid与list_order成了联合主键
二、Set集合属性映射
Set集合属性映射与List集合属性映射特别相似,但因为 Set是无序的、不可重复的集合,因此Set元素无需index元素来指定集合元素的次序。
Student表:
CREATE TABLE `student` ( `stuID` int(11) NOT NULL AUTO_INCREMENT, `stuname` varchar(32) DEFAULT NULL, PRIMARY KEY (`stuID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
Student_subject表:
CREATE TABLE `student_subject` ( `stuID` int(11) NOT NULL, `subject` varchar(255) NOT NULL, PRIMARY KEY (`stuID`,`subject`), KEY `FKBB 5C 1328D5394BCF` (`stuID`), CONSTRAINT `FKBB 5C 1328D5394BCF` FOREIGN KEY (`stuID`) REFERENCES `student` (`stuID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
PO:
public class Student implements Serializable {
private Integer stuID ; private String stuName ; private Set<String> subject = new HashSet<String>();
public Student() { } ........... } |
Student.hbm.xml
<hibernate-mapping> <class name="com.gxd.set.po.Student" table="student"> <id name="stuID" type="integer"> <column name="stuID" /> <generator class="native" /> </id> <property name="stuName" type="string"> <column name="stuname" length="32" /> </property> <!-- 映射SET集合属性,指定学生科目对应的数据表 --> <set name="subject" table="student_subject"> <!-- 集合属性的外键列 --> <key column="stuID" not-null="true"></key> <!-- 集合中的元素 --> <element type="string" column="subject" not-null="true"></element> </set> </class> </hibernate-mapping> |
TEST:
public static void main(String[] args) { Operator op = new Operator() ; Student stu = new Student() ; stu.setStuName("张三"); Set<String> subject = new HashSet<String>(); subject.add("语文"); subject.add("数学"); stu.setSubject(subject); op.addStudent(stu);
stu = new Student() ; stu.setStuName("李四"); subject = new HashSet<String>(); subject.add("语文"); subject.add("数学"); subject.add("外语"); stu.setSubject(subject);
op.addStudent(stu); }
public void addStudent(Student stu) { session.save(stu); session.beginTransaction().commit(); } |
控制台执行结果:
Hibernate: insert into student (stuname) values (?) Hibernate: insert into student_subject (stuID, subject) values (?, ?) Hibernate: insert into student_subject (stuID, subject) values (?, ?) Hibernate: insert into student (stuname) values (?) Hibernate: insert into student_subject (stuID, subject) values (?, ?) Hibernate: insert into student_subject (stuID, subject) values (?, ?) Hibernate: insert into student_subject (stuID, subject) values (?, ?) |
表结果:
我们发现stuID&subject成了联合主键,这是因为我们将element元素包括了not-null=”true”属性,如果不包含此属性,则student_subject表没有主键
三、Map集合属性映射
PO:
public class Config implements Serializable {
private int configID ; private String configDescribe ; private Map cfg = new HashMap(0) ;
public Map getCfg() { return cfg; } public void setCfg(Map cfg) { this.cfg = cfg; } public String getConfigDescribe() { return configDescribe; } public void setConfigDescribe(String configDescribe) { this.configDescribe = configDescribe; } public int getConfigID() { return configID; } public void setConfigID(int configID) { this.configID = configID; } }
|
Config.hbm.xml
<?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"> <hibernate-mapping> <class name="com.gxd.map.po.Config" table="config"> <id name="configID" type="integer"> <column name="CFGID" /> <generator class="native" /> </id> <property name="configDescribe" type="string"> <column name="CFGDESCRIBE" length="32" /> </property> <!-- 映射MAP集合属性 --> <map name="cfg" table="cfg"> <!-- 映射外键列 --> <key column="configID" not-null="true"/> <!-- 映射Map KEY --> <map-key type="string" column="cfgName"/> <!-- 映射Map VALUE --> <element type="string" column="cfgValue"/> </map> </class> </hibernate-mapping> |
测试:
public static void main(String[] args) { Operator op = new Operator() ; Config config = new Config() ; config.setConfigDescribe("网站名称"); Map cfg = new HashMap() ; cfg.put("siteName", "神彩飞扬技术在线"); config.setCfg(cfg); op.addConfig(config);
config = new Config() ; config.setConfigDescribe("网站域名"); cfg = new HashMap() ; cfg.put("siteDomain", "www.guoxiaodong.net"); config.setCfg(cfg); op.addConfig(config); }
public void addConfig(Config config) { session.save(config); session.beginTransaction().commit(); } |
测试二(这种方式是一样的)
public static void main(String[] args) { Operator op = new Operator() ; Config config = new Config() ; config.setConfigDescribe("网站名称"); config.getCfg().put("siteName", "神彩飞扬技术在线"); op.addConfig(config);
config = new Config(); config.setConfigDescribe("网站域名"); config.getCfg().put("siteDomain", "www.guoxiaodong.net"); op.addConfig(config); }
public void addConfig(Config config) { session.save(config); session.beginTransaction().commit(); } |
config表:
CREATE TABLE `config` ( `CFGID` int(11) NOT NULL AUTO_INCREMENT, `CFGDESCRIBE` varchar(32) DEFAULT NULL, PRIMARY KEY (`CFGID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
Cfg表:
CREATE TABLE `cfg` ( `configID` int(11) NOT NULL, `cfgValue` varchar(255) DEFAULT NULL, `cfgName` varchar(255) NOT NULL, PRIMARY KEY (`configID`,`cfgName`), KEY `FK1806453B90BB4` (`configID`), CONSTRAINT `FK1806453B90BB4` FOREIGN KEY (`configID`) REFERENCES `config` (`CFGID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
两个表均为Hibernate生成的表
控制台执行结果:
四、 映射引用属性
引用属性的意思是:持久化类的属性既不是基本数据类型,也不是Stirng字符串,而是某个引用变量,该引用属性的类型可以是自定义类。
PO:
public class Person implements Serializable{ private int id ; private int age ; private Name name ; //引用属性name .......... } |
public class Name { private String firstName ; private String lastName ; ....... } |
Person.hbm.xml:
<hibernate-mapping> <class name="com.gxd.component.po.Person" table="person"> <id name="id" type="integer"> <column name="personID" /> <generator class="native" /> </id> <property name="age" type="integer"> <column name="personAge"/> </property> <!-- 映射引用属性name,引用属性的类型为com.gxd.component.po.Name --> <component name="name" class="com.gxd.component.po.Name"> <!-- 映射引用属性的firstName值 --> <property name="firstName"/> <!-- 映射引用属性的lastName值 --> <property name="lastName"></property> </component> </class> </hibernate-mapping> |
测试:
public static void main(String[] args) { Operator op = new Operator() ; Person p = new Person() ; Name name = new Name() ; p.setAge(23); name.setFirstName("刘"); name.setLastName("德华"); p.setName(name) ; op.addPerson(p);
p = new Person() ; name = new Name(); p.setAge(18); name.setFirstName("林") ; name.setLastName("青霞") ; p.setName(name) ; op.addPerson(p); }
public void addPerson(Person person) { session.save(person); session.beginTransaction().commit(); } |
结果:
五、 集合引用属性映射
集合除了可以存放字符串外,还可以存放引用类型。
PO
:
public class Member implements Serializable { private static final long serialVersionUID = 1L ; private int id ; private String name ; private int age ; //存放了引用类型的集合属性 学历 private List<SchoolAge> schoolAge = new ArrayList<SchoolAge>() ; ....... } |
public class SchoolAge { private String name ; //学校名 private String schoolType ; //学校类型 private String address ; //学校地址 ......... } |
Member.hbm.xml
<hibernate-mapping> <class name="com.gxd.composite.po.Member" table="member"> <id name="id" type="integer"> <column name="memID" /> <generator class="native" /> </id> <property name="name" type="string"> <column name="memName"></column> </property> <property name="age" type="integer"> <column name="memAge"/> </property> <!-- 映射List集合属性 --> <list name="schoolAge" table="school_age"> <!-- 映射关联外键列 --> <key column="memID"/> <!-- List有序集合,需要索引 --> <list-index column="list_order"/> <!-- 映射集合里的元素并指定类型 --> <composite-element class="com.gxd.composite.po.SchoolAge"> <!-- 每个property属性映射集合元素的基本属性 --> <property name="name"/> <property name="schoolType"/> <property name="address"/> </composite-element> </list> </class> </hibernate-mapping> |
测试:
public static void main(String[] args) { Operator op = new Operator() ; Member member = new Member() ; SchoolAge schAge = new SchoolAge() ; member.setName("张三") ; member.setAge(21) ;
schAge.setName("郴州市一完小") ; schAge.setSchoolType("小学") ; schAge.setAddress("郴州市桔井路1号") ;
SchoolAge schAge2 = new SchoolAge() ; schAge2.setName("郴州市二中") ; schAge2.setSchoolType("中学") ; schAge2.setAddress("郴州市苏仙北路2号") ;
member.getSchoolAge().add(schAge) ; member.getSchoolAge().add(schAge2) ; op.addMember(member) ; }
public void addMember(Member member) { session.save(member); session.beginTransaction().commit(); } |
结果:
未完待续……