《Hibernate学习笔记之三》:联合主键的映射
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了《Hibernate学习笔记之三》:联合主键的映射,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含11323字,纯文字阅读大概需要17分钟。
内容图文
《Hibernate学习笔记之三》:联合主键的映射
就如在前面所举的例子一样,是使用的id作为唯一的主键,一般情况下我们也只使用唯一的一个属性作为主键,但是在实际中,我们可能会遇到几个属性作为主键的情况,因此,在本篇博文中,就来介绍下,联合主键的映射关系应该如何来做??
联合主键的映射有两种方式来进行实现。
1、使用映射文件 XXX.bhm.xml
2、使用Annotation
Hibernate首先需要使用联合主键的实体类必须实现Serializable接口,即为了使序列能够被序列化进行传输,并要求实体类重写equals、hashCode这两个方法,用这两个方法来确保联合主键的唯一性。
下面具体来看一个例子。
先看第一种实现方式。
第一种:使用映射文件XXX.bhm.xml来实现联合主键的映射
a、实体类 Student
package com.hibernate.model;
publicclass Student {
private StudentPK pk;//主键public StudentPK getPk() {
return pk;
}
publicvoidsetPk(StudentPK pk) {
this.pk = pk;
}
privateint age;
publicintgetAge() {
return age;
}
publicvoidsetAge(int age) {
this.age = age;
}
}
上面的private StudentPK pk;就是我们的联合主键,联合主键我们封装在了一个类StudentPK中,也可以之间将联合主键的属性不进行封装,直接写在实体类Student。
b、联合主键类 StudentPK
这个就是对联合主键id和name进行了封装,即使得StudentPK为联合主键类,这个类要实现Serializable接口,并需要重写equals和hashCode方法。来实现组合的标识符的相等判断
package com.hibernate.model;
import java.io.Serializable;
publicclassStudentPKimplementsSerializable{privateint id;
private String name;
publicintgetId() {
return id;
}
publicvoidsetId(int id) {
this.id = id;
}
public String getName() {
return name;
}
publicvoidsetName(String name) {
this.name = name;
}
@Overridepublicbooleanequals(Object o){
if (o instanceof StudentPK) {
StudentPK pk = (StudentPK) o;
if(this.id==pk.getId()&&this.name.equals(pk.getName())){
returntrue;
}
}
returnfalse ;
}
@OverridepublicinthashCode(){
returnthis.name.hashCode();
}
}
c、联合主键的映射文件 Student.bhm.xml
在前面的例子中我们见到过一个属性作为主键的映射文件如何来写,下面就是几个属性作为主键的映射文件应该如何来写。
在官方文档上有这样一句话:
定义可以访问旧式的多主键数据。 我们强烈不建议使用这种方式。
文档上面给出的composite-id的一般格式如下:
<composite-idname="propertyName"class="ClassName"
mapped="true|false"
access="field|property|ClassName"
node="element-name|."
>
<key-propertyname="propertyName" type="typename" column="column_name"/>
<key-many-to-one name="propertyName class="ClassName" column="column_name"/>
......
</composite-id>
在我们的例子中完整的映射文件内容如下:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mappingpackage="com.hibernate.model">
<classname="Student"table="Student">
<!-- 如果我们不写table,则默认表名与类名一致 -->
<!-- 联合主键 -->
<composite-idname="pk"class="com.hibernate.model.StudentPK">
<key-propertyname="id"column="id" />
<key-propertyname="name"column="name"type="string"/>
</composite-id>
<!-- 其他属性,name对应实体类的属性,column对应关系型数据库表的列 -->
<propertyname="age"/>
</class>
</hibernate-mapping>
d、配置文件 hibernate.cfg.xml
配置文件内容如下:
<?xml version=‘1.0‘ encoding=‘utf-8‘?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<propertyname="connection.driver_class">com.mysql.jdbc.Driver</property><propertyname="connection.url">jdbc:mysql://localhost/hibernate</property><!-- hibernate为数据库名称 --><!-- 数据库的用户名和密码 --><propertyname="connection.username">root</property><propertyname="connection.password">123456</property><!-- JDBC connection pool (use the built-in) --><propertyname="connection.pool_size">1</property><!-- SQL dialect 主要看你使用的是那种数据库 --><propertyname="dialect">org.hibernate.dialect.MySQLDialect</property><!-- Enable Hibernate‘s automatic session context management --><propertyname="current_session_context_class">thread</property><!-- Disable the second-level cache --><propertyname="cache.provider_class">org.hibernate.cache.NoCacheProvider</property><!-- Echo all executed SQL to stdout --><propertyname="show_sql">true</property><!-- 按一定的格式来进行打印MySQL的SQL语句 --><propertyname="format_sql">true</property><!-- Drop and re-create the database schema on startup --><!-- 属性hbm2ddl.auto 可选值有:create|update|drop-create|invalide
create 每次都会给你新建一个表,因此存在数据丢失
update 当你的实体类中添加或删除了其他的属性,即将导致相应的表结构发生变化,因此会更改表的结构
invalide 即对象关系映射的检查。
--><propertyname="hbm2ddl.auto">update</property><!-- Student类与表Student的映射关系 --><mappingresource="com/hibernate/model/Student.hbm.xml"/></session-factory></hibernate-configuration>
e、测试类 StudentTest
测试类代码如下:
package com.hibernate.model;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
publicclassStudentTest {privatestatic SessionFactory sf=null;
@BeforeClasspublicstaticvoidbeforeClass(){
//读取配置 文件 hibernate.cfg.xml
Configuration cf= new Configuration().configure();
sf=cf.buildSessionFactory();
}
@TestpublicvoidtestSaveStudent() {
//获取 Session
Session session=sf.openSession();
//开启事务
session.beginTransaction();
StudentPK pk=new StudentPK();
pk.setId(2);
pk.setName("wuranghao");
Student student=new Student();
student.setPk(pk);
student.setAge(19);
//对持久化对象 进行 增删改查 操作
session.save(student);
session.getTransaction().commit();
session.close();
}
@AfterClasspublicstaticvoidafterClass(){
sf.close();
}
}
运行结果在数据库中的反应如下:
这样我们就完成了联合主键的映射。
第二种:使用Annotation来实现联合主键的映射
在文档中,说明了定义组合主键的几张语法如下:
1、将组件类注解为@Embeddable,并将组件的属性注解为@Id。
2、将组件的属性注解为@EmbeddedId
3、将类注解为@IdClass,并将该实体中所有属于主键的属性都注解为@Id。
下面对这三种方式分别举例来进行介绍。
1、将组件类注解为@Embeddable,并将组将的属性注解为@Id。
第一步:将组件类注解为@Embeddable
package com.hibernate.model;
import java.io.Serializable;
import javax.persistence.Embeddable;
/*第一步:将组件类注解为@Embeddable,而第二步并不是在此类中把id和name用注解@Id修饰,
而是在Teacher类中将TeacherPK组件*/@EmbeddablepublicclassTeacherPKimplementsSerializable{privateint id;
private String name;
publicintgetId() {
return id;
}
publicvoidsetId(int id) {
this.id = id;
}
public String getName() {
return name;
}
publicvoidsetName(String name) {
this.name = name;
}
@Overridepublicbooleanequals(Object o){
if (o instanceof TeacherPK) {
TeacherPK pk = (TeacherPK) o;
if(this.id==pk.getId()&&this.name.equals(pk.getName())){
returntrue;
}
}
returnfalse ;
}
@OverridepublicinthashCode(){
returnthis.name.hashCode();
}
}
第二步:将组件的属性注解为@Id
这里要特别注意的是:并不是在TeacherPK这个组合主键类中把id和name用注解@Id修饰,而是在实体类Teacher类中将TeacherPK组件用@Id来进行注释
package com.hibernate.model;
import javax.persistence.Entity;
import javax.persistence.Id;
@EntitypublicclassTeacher {private TeacherPK pk;//主键引用private String title;
@Idpublic TeacherPK getPk() {
return pk;
}
publicvoidsetPk(TeacherPK pk) {
this.pk = pk;
}
public String getTitle() {
return title;
}
publicvoidsetTitle(String title) {
this.title = title;
}
}
测试类
配置文件hibernate.cfg.xml和上面的一样,这里就不再贴代码,而测试类的代码如下:
package com.hibernate.model;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
publicclassTeacherTest {privatestatic SessionFactory sf=null;
@BeforeClasspublicstaticvoidbeforeClass(){
//读取配置 文件 hibernate.cfg.xml
Configuration cf= new Configuration().configure();
sf=cf.buildSessionFactory();
}
@TestpublicvoidtestSaveTeacher() {
//获取 Session
Session session=sf.openSession();
//开启事务
session.beginTransaction();
TeacherPK pk=new TeacherPK();//联合主键对象
pk.setId(3);
pk.setName("xiaoming");
Teacher t=new Teacher();
t.setPk(pk);
t.setTitle("professior");
//对持久化对象 进行 增删改查 操作
session.save(t);
session.getTransaction().commit();
session.close();
}
@AfterClasspublicstaticvoidafterClass(){
sf.close();
}
}
在控制台输出的建表数据如下:
因此,利用将组件类注解为@Embeddable,并将组件的属性注解为@Id。这种方式我们就成功的对联合主键进行了映射。
2、将组件的属性注解为@EmbeddedId
这种方式比第一种方式更加简单,直接不需要将组件类TeacherPK用注解为@Embeddable,而是直接用@EmbeddedId来注解Teacher类中的主键属性,如下:
package com.hibernate.model;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
@EntitypublicclassTeacher {private TeacherPK pk;//主键引用private String title;
//联合主键映射的第二种方式:直接将组件用注解@EmbeddedId来进行修饰@EmbeddedIdpublic TeacherPK getPk() {
return pk;
}
publicvoidsetPk(TeacherPK pk) {
this.pk = pk;
}
public String getTitle() {
return title;
}
publicvoidsetTitle(String title) {
this.title = title;
}
}
主键类TeacherPK不需要任何的注解。
package com.hibernate.model;
import java.io.Serializable;
publicclassTeacherPKimplementsSerializable{privateint id;
private String name;
publicintgetId() {
return id;
}
publicvoidsetId(int id) {
this.id = id;
}
public String getName() {
return name;
}
publicvoidsetName(String name) {
this.name = name;
}
@Overridepublicbooleanequals(Object o){
if (o instanceof TeacherPK) {
TeacherPK pk = (TeacherPK) o;
if(this.id==pk.getId()&&this.name.equals(pk.getName())){
returntrue;
}
}
returnfalse ;
}
@OverridepublicinthashCode(){
returnthis.name.hashCode();
}
}
3、将类注解为@IdClass,并将该实体中所有属于主键的属性都注解为@Id。
实体类Teacher
将实体类Teacher注解为@IDClass,并将实体中所有属性主键的属性都注解为@Id,而主键类TeacherPK则不用任何注解来进行修饰。
package com.hibernate.model;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
@Entity@IdClass(value=TeacherPK.class)
publicclassTeacher {//private TeacherPK pk;//主键引用privateint id;
private String name;
private String title;
@IdpublicintgetId() {
return id;
}
publicvoidsetId(int id) {
this.id = id;
}
@Idpublic String getName() {
return name;
}
publicvoidsetName(String name) {
this.name = name;
}
// public TeacherPK getPk() {// return pk;// }// public void setPk(TeacherPK pk) {// this.pk = pk;// }public String getTitle() {
return title;
}
publicvoidsetTitle(String title) {
this.title = title;
}
}
主键类代码如下:
不用任何注解来进行修饰。
package com.hibernate.model;
import java.io.Serializable;
publicclassTeacherPKimplementsSerializable{privateint id;
private String name;
publicintgetId() {
return id;
}
publicvoidsetId(int id) {
this.id = id;
}
public String getName() {
return name;
}
publicvoidsetName(String name) {
this.name = name;
}
@Overridepublicbooleanequals(Object o){
if (o instanceof TeacherPK) {
TeacherPK pk = (TeacherPK) o;
if(this.id==pk.getId()&&this.name.equals(pk.getName())){
returntrue;
}
}
returnfalse ;
}
@OverridepublicinthashCode(){
returnthis.name.hashCode();
}
}
测试类代码如下:
package com.hibernate.model;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
publicclassTeacherTest {privatestatic SessionFactory sf=null;
@BeforeClasspublicstaticvoidbeforeClass(){
//读取配置 文件 hibernate.cfg.xml
Configuration cf= new Configuration().configure();
sf=cf.buildSessionFactory();
}
@TestpublicvoidtestSaveTeacher() {
//获取 Session
Session session=sf.openSession();
//开启事务
session.beginTransaction();
// TeacherPK pk=new TeacherPK();//联合主键对象// pk.setId(3);// pk.setName("xiaoming");
Teacher t=new Teacher();
t.setId(2);
t.setName("zhangsan");
t.setTitle("professior");
//对持久化对象 进行 增删改查 操作
session.save(t);
session.getTransaction().commit();
session.close();
}
@AfterClasspublicstaticvoidafterClass(){
sf.close();
}
}
hibernate.cfg.xml文件内容与上面介绍的一样。
运行程序后在数据库中Teacher表结构如下:
以上就是第三种注解方式来完成联合主键的映射。
原文:http://blog.csdn.net/u010412719/article/details/51275744
内容总结
以上是互联网集市为您收集整理的《Hibernate学习笔记之三》:联合主键的映射全部内容,希望文章能够帮你解决《Hibernate学习笔记之三》:联合主键的映射所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。