主键映射和Hibernate映射
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了主键映射和Hibernate映射相关的知识,希望对你有一定的参考价值。
组件映射
类组合关系的映射,也叫做组件映射!
注意:组件类和被包含的组件类,共同映射到一张表!
需求: 如汽车与车轮
代码示例:
1、JavaBean
Wheel.java
package com.gqx.component; /** * 车轮 * @author 郭庆兴 * */ public class Wheel { private int count; private int size; public int getCount() { return count; } public void setCount(int count) { this.count = count; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } }
Car.java
package com.gqx.component; public class Car { private int id; private String brand; //车轮 private Wheel wheel; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public Wheel getWheel() { return wheel; } public void setWheel(Wheel wheel) { this.wheel = wheel; } }
2、映射文件
<?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.gqx.component"> <class name="Car" table="t_car" > <id name="id"> <generator class="native"></generator> </id> <property name="brand" length="20"></property> <!-- 组件映射 --> <component name="wheel"> <property name="count"></property> <property name="size"></property> </component> </class> </hibernate-mapping>
3、测试程序
package com.gqx.component; import static org.junit.Assert.*; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.junit.AfterClass; import org.junit.Test; import com.gqx.collection.User; public class App { private static SessionFactory sf; static{ sf=new Configuration().configure() .addClass(Car.class) .buildSessionFactory(); } @Test public void test() { Session session=sf.openSession(); session.beginTransaction(); //轮子 Wheel wheel=new Wheel(); wheel.setCount(4); wheel.setSize(40); //汽车 Car car=new Car(); car.setBrand("BMW"); car.setWheel(wheel); //保存 session.save(car); session.getTransaction().commit(); session.close(); } }
继承映射
如:父类——动物
子类:猫,猴子
1、JavaBean文件
Animal.java
package com.gqx.extends1; /** * 动物类 * @author 郭庆兴 * */ public abstract class Animal { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Cat.java
package com.gqx.extends1; public class Cat extends Animal { //抓老鼠 private String catchMouse; public String getCatchMouse() { return catchMouse; } public void setCatchMouse(String catchMouse) { this.catchMouse = catchMouse; } }
Monkey.java
package com.gqx.extends2; public class Monkey extends Animal{ //吃香蕉 private String eatBanana; public String getEatBanana() { return eatBanana; } public void setEatBanana(String eatBanana) { this.eatBanana = eatBanana; } }
2、映射文件
简单继承映射
<?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.gqx.extends1"> <class name="Cat" table="t_cat" > <id name="id"> <generator class="native"></generator> </id> <property name="catchMouse" length="20"></property> <property name="name" length="20"></property> </class> </hibernate-mapping>
3、测试文件
package com.gqx.extends1; import static org.junit.Assert.*; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.junit.AfterClass; import org.junit.Test; import com.gqx.collection.User; public class App { private static SessionFactory sf; static{ sf=new Configuration().configure() .addClass(Cat.class) .buildSessionFactory(); } @Test public void test() { Session session=sf.openSession(); session.beginTransaction(); Cat cat=new Cat(); cat.setName("龙猫"); cat.setCatchMouse("抓小老鼠"); session.save(cat); session.getTransaction().commit(); session.close(); } @Test public void testGet() { Session session=sf.openSession(); session.beginTransaction(); // Query q=session.createQuery("from Cat"); // List<Cat> list=q.list(); // 如果通过父类查询,需要说明包 Query q=session.createQuery("from com.gqx.extends1.Cat"); List<Animal> list=q.list(); System.out.println(list); session.getTransaction().commit(); session.close(); } }
映射文件也可以分为三种类型去实现
一、所有子类映射到一张表 (1张表)
什么情况用?
子类教多,且子类较为简单,即只有个别属性!
好处:因为使用一个映射文件, 减少了映射文件的个数。
缺点:(不符合数据库设计原则)
一个映射文件: Animal.hbm.xml
<?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.gqx.extends2"> <class name="Animal" table="t_animal" > <id name="id"> <generator class="native"></generator> </id> <!-- 指定鉴别器字段(区分不同的子类) --> <discriminator column="type_"></discriminator> <property name="name" length="20"></property> <!-- 每个子类都用subclass映射 注意:一定要指定鉴别器字段,否则报错! 鉴别器字段:作用是在数据库中区别每一个子类信息,就是一个列的信息 --> <!-- 子类:猫 discriminator-value: 指定鉴别器字段,即type_字段的值 如果不指定,默认为当前子类的全名 --> <subclass name="Cat" discriminator-value="cat_"> <property name="catchMouse"></property> </subclass> <!-- 子类:狗 --> <subclass name="Monkey" discriminator-value="monkey_"> <property name="eatBanana"></property> </subclass> </class> </hibernate-mapping>
结果如图:
总结:
写法较为简单:所有子类用一个映射文件,且映射到一张表!
但数据库设计不合理!
二、每个类映射一张表(3张表)
数据库
T_anmal (存储父类信息)
T_cat (引用父类的主键)
T_monkey(引用父类的主键)
映射文件
<?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.gqx.extends3"> <class name="Animal" table="t_animal" > <id name="id"> <generator class="native"></generator> </id> <property name="name" length="20"></property> <!-- 子类:猫 t_cat key:指定cat表的外键字段 --> <joined-subclass name="Cat" table="t_cat"> <key column="t_animal_id"></key> <property name="catchMouse"></property> </joined-subclass> <!-- 子类:猴子 t_monkey --> <joined-subclass name="Monkey" table="t_monkey"> <key column="t_animal_id"></key> <property name="eatBanana"></property> </joined-subclass> </class> </hibernate-mapping>
总结:
一个映射文件,存储所有的子类; 子类父类都对应表;
缺点:表结构比较负责,插入一条子类信息,需要用2条sql: 往父类插入、往子类插入!
三、(推荐)每个子类映射一张表, 父类不对应表(2张表)
这个时候要把Animal类的id改一下
private String id;
映射文件
<?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.gqx.extends4"> <!-- abstract="true" 指定实体对象不对应表,即在数据库端不生成表 --> <class name="Animal" abstract="true"> <!-- 如果用union-subclass节点,主键生成策略不能为自增长 --> <id name="id"> <generator class="uuid"></generator> </id> <property name="name" length="20"></property> <!-- union-subclass table 指定为表名,表的主键即为id列 --> <!-- 子类:猫 t_cat--> <union-subclass name="Cat" table="t_cat"> <property name="catchMouse"></property> </union-subclass> <!-- 子类:猴子 t_monkey--> <union-subclass name="Monkey" table="t_monkey"> <property name="eatBanana"></property> </union-subclass> </class> </hibernate-mapping>
以上是关于主键映射和Hibernate映射的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate—— 联合主键 一对一关联关系映射(xml和注解) 和 领域驱动设计
Hibernate之关联关系映射(一对一主键映射和一对一外键映射)
hibernate中基于主键映射1-1关联关系和基于外键映射1-1关联关系的不同