Hibernate一对一关联
一对一单向外键关联
1.建Husband实体类和Wife实体类,添加Annotation注解,如下
@Entity public class Husband { private int id; private String name; private Wife wife; @Id @GeneratedValue 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; } @OneToOne //Husband和Wife是一对一的关系 public Wife getWife() { return wife; } public void setWife(Wife wife) { this.wife = wife; } }
@Entity public class Wife { private int id; private String name; @Id @GeneratedValue 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; } }
2.在hibernate.cfg.xml中添加mapping语句
<mapping class="com.hibernate.model.Husband"/> <mapping class="com.hibernate.model.Wife"/>
3.建Junit测试类
public class ORMappingTest { @Test public void test() { //生成表,输出建表语句 new SchemaExport(new Configuration().configure()).create(true, true); } }
程序至此结束,运行程序,在数据库中生成Husband表和Wife表,并在控制台输出建表语句。
Husband表中会自动生成属性名为“wife_id”的外键,参考表为Wife表。
如果想要使用自定义的外键属性名,可对Husband实体类的getWife方法添加Annotation注解,如下:
@OneToOne //Husband和Wife是一对一的关系 @JoinColumn(name="wifeId") // java默认生成的外键属性名为wife_id.设置此项后,可以任意设定其属性名,此处设置为wifeId. public Wife getWife() { return wife; }
一对一双向外键关联
1.建Husband实体类和Wife实体类,添加Annotation注解
Husband类同上,只需在Wife类中增加一个Husband类型的变量,并添加@OneToOne注解即可,如下
@Entity public class Wife { private int id; private String name; private Husband husband; //建一个Husband类型的变量,并生成setter和getter方法 @Id @GeneratedValue 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; } @OneToOne(mappedBy="wife") //"wife"指的是Husband类中的private Wife wife; public Husband getHusband() { return husband; } public void setHusband(Husband husband) { this.husband = husband; } }
凡是双向关联,必设mappedBy
2.在hibernate.cfg.xml中添加mapping语句----同上
3.建Junit测试类----同上
程序至此结束,运行程序,在数据库中生成Husband表和Wife表,并在控制台输出建表语句。
联合主键
联合主键(3种方式)
将主键类注解为@Embeddable,并将主键(pk)的属性注解为@Id (不常用)
将主键的属性注解为@EmbeddedId
将实体类注解为@IdClass(组件类.class),并将该实体类中所有属于主键的属性都注解为@Id
示例:建Wife表,属性有id,name,age。其中id和name为联合主键
1.建主键类WifePK
/* * 建立主键类WifePK * 需实现Serializable接口,此接口用于把当前类的接口进行序列化 * 需重写equals()和hashCode()方法,以保证对象的唯一性 * **/ public class WifePK implements java.io.Serializable{ 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; } @Override public boolean equals(Object o){ if(o instanceof WifePK){ WifePK pk = (WifePK) o; if(this.id == pk.getId() && this.name.equals(pk.getName())){ return true; } } return false; } @Override public int hashCode(){ return this.name.hashCode(); } }
2.建实体类Wife
第二种方式注解,@EmbeddedId
@Entity public class Wife { private WifePK pk; //增加WifePK类型的变量,并添加getter和setter方法 private int age; @EmbeddedId //将其注解为联合主键 public WifePK getPk() { return pk; } public void setPk(WifePK pk) { this.pk = pk; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
第三种方式注解,@IdClass
@Entity @IdClass(WifePK.class) //将实体类注解为@IdClass public class Wife { private int id; private String name; private int age; @Id //将该实体类中属于主键的属性注解为@Id public int getId() { return id; } public void setId(int id) { this.id = id; } @Id //将该实体类中属于主键的属性注解为@Id public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
3.写Junit测试类
第二种方式注解,@EmbeddedId
public class WifeTest { private static SessionFactory sf = null; @BeforeClass public static void beforeClass() { sf = new Configuration().configure().buildSessionFactory(); } @AfterClass public static void afterClass() { sf.close(); } @Test public void test() { WifePK pk = new WifePK(); pk.setId(1); pk.setName("zhangsan"); Wife wife = new Wife(); wife.setPk(pk); wife.setAge(32); Session session = sf.getCurrentSession(); session.beginTransaction(); session.save(wife); session.getTransaction().commit(); } }
第三种方式注解,@IdClass,只需修改其test()方法,如下:
@Test public void test() { Wife wife = new Wife(); wife.setId(1); wife.setName("zhangsan"); wife.setAge(32); Session session = sf.getCurrentSession(); session.beginTransaction(); session.save(wife); session.getTransaction().commit(); }
程序至此结束,运行程序,在数据库中生成Wife表,id和name为主键,并将对象wife存入Wife表。
联合主键关联
示例:
建Husband表,属性有id和name
建Wife表,属性有id,name,age。其中id和name为联合主键
设置联合主键关联,在Husband表中生成属性名为wife_id和wife_name的外键,分别参考Wife表中的id和name
1.建Husband实体类、Wife实体类和WifePK主键类,添加Annotation注解
Husband类,同上
WifePK类,同上
Wife类,同“联合主键”部分第三种方式注解的Wife实体类
2.在hibernate.cfg.xml中添加mapping语句----同上
3.建Junit测试类ORMappingTest----同上
程序至此结束,运行程序,在数据库中生成Husband表和Wife表,并在控制台输出建表语句。
Husband表中会自动生成属性名为“wife_id”和“wife_name”的外键,参考表为Wife表。
如果想要使用自定义的外键属性名,可对Husband实体类的getWife方法添加Annotation注解,如下:
@OneToOne @JoinColumns( { @JoinColumn(name="wifeId",referencedColumnName="id"), @JoinColumn(name="wifeName",referencedColumnName="name") } ) public Wife getWife() { return wife; }
组件映射
除了粗粒度的对象模型设计(一个表映射成一个持久化类)之外,还可以采用细粒度的对象模型,把一个表映射成两个或者多个类。
被细化出来的类,可以称为组件(Component)。
组件是某个实体的逻辑组成部分,它与实体的本质区别在于组件没有id,可以把组件当做值对象。
举例来说:Husband类有id、name、wifeName、wifeAge等属性,将wifeName、wifeAge从Husband实体类中拿出来,单独建一个Wife类,这个类就叫做值对象,也就是所说的组件。表现在数据库中,将只有husband一张表,有id、name、wifeName、wifeAge属性。
采用组件映射的优点:实现了对象细粒度的划分,层次更加分明,复用率高。
1.建立Husband实体类和Wife组件类,添加Annotation注解
Husband类同上,只是不需要添加@OneToOne注解,改为@Embedded注解,如下:
@Embedded public Wife getWife() { return wife; }
Wife类无需添加任何注解,如下:
public class Wife { private String wifeName; private int wifeAge; public String getWifeName() { return wifeName; } public void setWifeName(String wifeName) { this.wifeName = wifeName; } public int getWifeAge() { return wifeAge; } public void setWifeAge(int wifeAge) { this.wifeAge = wifeAge; } }
2.在hibernate.cfg.xml中添加mapping语句
只需添加Husband的mapping,Wife类不是实体类,无需添加。
3.建Junit测试类ORMappingTest----同上
程序至此结束,运行程序,在数据库中生成Husband表,并在控制台输出建表语句。
Husband表中有id、name、wifeName、wifeAge属性。