Java进阶知识06 Hibernate联合主键之Annotation(注解)和XML实现方式

1、Hibernate联合主键(Annotation实现)

1.1、单列主键  

    1.1.1、为什么要有主键? //唯一确定一条记录
    1.1.2、一个表能否有多个主键? //不能
    1.1.3、为什么把id设为主键? //如果有其他的方式可以作为主键,id可以不要
    1.1.4、主键生成策略:
        identity:自增长,对DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的内置标识字段提供支持。 返回的标识符是long, short 或者int类型的。
        sequence:自增长,在DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence), 而在Interbase中使用生成器(generator)。返回的标识符是long, short或者 int类型的。
        native:自增长,根据底层数据库的能力选择identity, sequence 或者hilo中的一个。如果是mysql,自动选择identity,如果是oracle,自动选择sequence 。
        increment:自增长,只有在没有其他进程往同一张表中插入数据时才能使用。 在集群下不要使用
        assigned:指定主键生成策略
        uuid:随机生成唯一值(String类型)

1.2、联合主键类必须要序列化,并重写equals和hashCode方法  

    主键类为什么要序列化?如果多个该类对象同时放入内存中,在一个集群系统中,其中一台服务器如果down机了,需要将内存中对象写到其它服务器。同时,如果该服务器内存已满,需要用虚拟内存,这就需要序列化后才能写到硬盘上。

1.3、注解  

    @Entity
    @Table(name=”XXXX”)  //类名和表名一样,可省略不写
    @Column(.....)
     A.实现方式一:将联合主键类注解为@Embeddable、将对象中联合主键注解为@Id
     B.实现方式二:在对象中把联合主键引用注解为@EmbeddedId
     C.实现方式三:在对象中包含联合主键的字段、并将其都注解为@Id,并在该对象类上注解@IdClass(联合主键类.class)

1.4、实例  

1.4.1、创建一个实体类Student和StudentPK:联合主键类序列化,重写equals和hashCode方法

StudentPK  实体类:

 1 package com.shore.entity;
 2 
 3 import java.io.Serializable;
 4 
 5 import javax.persistence.Entity;
 6 
 7 /**
 8  * @author DSHORE/2019-9-16
 9  * 
10  */
11 
12 @Entity
13 public class StudentPK implements Serializable {
14     private static final long serialVersionUID = -2060041603022800114L; //序列化
15     
16     // name+address作为联合主键
17     private String name;
18     private String address;
19     
20     public StudentPK() {
21         super();
22     }
23     public StudentPK(String name, String address) {
24         super();
25         this.name = name;
26         this.address = address;
27     }
28 
29     public String getName() {
30         return name;
31     }
32     public void setName(String name) {
33         this.name = name;
34     }
35 
36     public String getAddress() {
37         return address;
38     }
39     public void setAddress(String address) {
40         this.address = address;
41     }
42     
43     //联合主键类序列化,重写equals和hashCode方法
44     @Override
45     public boolean equals(Object object) {
46         // instanceof——判断左边对象是否为右边对象的实例
47         if (object instanceof StudentPK) {
48             StudentPK pk = (StudentPK) object;
49             if (this.name.equals(pk.getName())
50                     && this.address.equals(pk.getAddress())) {
51                 return true;
52             }
53         }
54         return false;
55     }
56 
57     @Override
58     public int hashCode() {
59         return this.name.hashCode();
60     }
61 }

Student 实体类:

 1 package com.shore.entity;
 2 
 3 import java.io.Serializable;
 4 
 5 import javax.persistence.EmbeddedId;
 6 import javax.persistence.Entity;
 7 
 8 import org.hibernate.annotations.Type;
 9 
10 /**
11  * @author DSHORE/2019-9-16
12  *
13  */
14 
15 @Entity
16 public class Student implements Serializable {
17     //对应的Student对象类建议也要序列化,但是可以不重写equals和hashCode方法
18     private static final long serialVersionUID = -2924879320015689901L;
19     
20     private StudentPK keys;//联合主键 别名
21     private Boolean sex;
22     private String hobby;
23     
24     public Student() {
25         super();
26     }
27     public Student(StudentPK keys, Boolean sex, String hobby) {
28         super();
29         this.keys = keys;
30         this.sex = sex;
31         this.hobby = hobby;
32     }
33     
34     @EmbeddedId  //指定keys为联合主键
35     public StudentPK getKeys() {
36         return keys;
37     }
38     public void setKeys(StudentPK keys) {
39         this.keys = keys;
40     }
41     
42     @Type(type = "yes_no")  //数据库中,会以Y/N的形式插入到sex字段中
43     public Boolean getSex() {
44         return sex;
45     }
46     public void setSex(Boolean sex) {
47         this.sex = sex;
48     }
49     
50     public String getHobby() {
51         return hobby;
52     }
53     public void setHobby(String hobby) {
54         this.hobby = hobby;
55     }
56 }

1.4.2、创建hibernate.cfg.xml配置文件

 1 <?xml version='1.0' encoding='utf-8'?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 5 
 6 <hibernate-configuration>
 7     <session-factory>
 8         <!-- Database connection settings -->
 9         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
10         <property name="connection.url">jdbc:mysql://localhost:3306/school</property>
11         <property name="connection.username">root</property>
12         <property name="connection.password">123456</property>
13 
14         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
15         <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
16         <property name="show_sql">true</property>
17         <property name="hbm2ddl.auto">create</property>
18 
19         <!-- <mapping resource="com/shore/entity/Student.hbm.xml"/> -->
20         <mapping class="com.shore.entity.Student" />
21     </session-factory>
22 </hibernate-configuration>

联合主键,MySQL数据库的写法:(本文不需要手动创建数据表,是自动创建的,下面的MySQL建表脚本,仅提供参考)

1 CREATE TABLE student(
2   name VARCHAR(20),
3   address VARCHAR(100),
4   sex BOOLEAN,
5   hobby VARCHAR(60),
6   PRIMARY KEY(name,address)  -- 联合主键
7 )

1.4.3、创建测试类CompositeKeyTest ,开始测试:

 1 package com.shore.test;
 2 
 3 import org.hibernate.Session;
 4 import org.hibernate.SessionFactory;
 5 import org.hibernate.Transaction;
 6 import org.hibernate.cfg.AnnotationConfiguration;
 7 import org.junit.AfterClass;
 8 import org.junit.BeforeClass;
 9 import org.junit.Test;
10 
11 import com.shore.entity.Student;
12 import com.shore.entity.StudentPK;
13 
14 /**
15  * @author DSHORE/2019-9-16
16  *
17  */
18 public class CompositeKeyTest {
19     public static SessionFactory sessionFactory = null;
20     public static Session session = null;
21     
22     @BeforeClass
23     public static void buildSessionFactory() {
24                         //联合主键之Annotation实现,用的是AnnotationConfiguration方法
25         sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
26     }
27     
28     @AfterClass
29     public static void close() {
30         session.close();
31         sessionFactory.close();
32     }
33     
34     @Test
35     public void test() {
36         session = sessionFactory.openSession();//打开一个session
37         Transaction transaction = session.beginTransaction();//开启事务
38         Student student = new Student(new StudentPK("zhansan", "xxxxxx"), true, "yundong");    
39         session.save(student);
40         transaction.commit();//提交事务
41     }
42 }

1.4.4、测试结果图:

 

       

 

 

 2、Hibernate联合主键(XML实现)

代码和上面的全部一样,不一样的地方如下所示:

2.1、首先,注解得全部去掉。

2.2、多了一个配置文件:student.hbm.xml

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC
 3         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4         "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5         
 6 <hibernate-mapping package="com.shore.entity">
 7     <class name="Student">  
 8         <composite-id name="keys">
 9             <key-property name="name"/>
10             <key-property name="address"/>
11         </composite-id>
12         <property name="sex" type="java.lang.Boolean"/>
13         <property name="hobby" type="java.lang.String"/> 
14     </class>
15 </hibernate-mapping>

2.3、最后在hibernate.cfg.xml配置文件中引入“student.hbm.xml”文件即可

 1 <?xml version='1.0' encoding='utf-8'?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 5 
 6 <hibernate-configuration>
 7     <session-factory>
 8         <!-- Database connection settings -->
 9         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
10         <property name="connection.url">jdbc:mysql://localhost:3306/school</property>
11         <property name="connection.username">root</property>
12         <property name="connection.password">123456</property>
13 
14         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
15         <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
16         <property name="show_sql">true</property>
17         <property name="hbm2ddl.auto">create</property>
18 
19         <mapping resource="com/shore/entity/Student.hbm.xml"/>
20         <!-- <mapping class="com.shore.entity.Student" /> -->
21     </session-factory>
22 </hibernate-configuration>

2.4、还有sessionFactory创建方式不一样:

 1 package com.shore.test;
 2 
 3 import org.hibernate.Session;
 4 import org.hibernate.SessionFactory;
 5 import org.hibernate.Transaction;
 6 import org.hibernate.cfg.AnnotationConfiguration;
 7 import org.junit.AfterClass;
 8 import org.junit.BeforeClass;
 9 import org.junit.Test;
10 
11 import com.shore.entity.Student;
12 import com.shore.entity.StudentPK;
13 
14 /**
15  * @author DSHORE/2019-9-16
16  *
17  */
18 public class CompositeKeyTest2 {
19     public static SessionFactory sessionFactory = null;
20     public static Session session = null;
21     
22     @BeforeClass
23     public static void buildSessionFactory() {
24                         //联合主键之xml实现,用的是Configuration()方法
25         sessionFactory = new Configuration().configure().buildSessionFactory(); //之前用的是:AnnotationConfiguration()
26     }
27     
28     @AfterClass
29     public static void close() {
30         session.close();
31         sessionFactory.close();
32     }
33     
34     @Test
35     public void test() {
36         session = sessionFactory.openSession();//打开一个session
37         Transaction transaction = session.beginTransaction();//开启事务
38         Student student = new Student(new StudentPK("zhansan", "xxxxxx"), true, "yundong");    
39         session.save(student);
40         transaction.commit();//提交事务
41     }
42 }

 

 

 

 

 

原创作者:DSHORE

作者主页:http://www.cnblogs.com/dshore123/

原文出自:https://www.cnblogs.com/dshore123/p/11528059.html

欢迎转载,转载务必说明出处。(如果本文对您有帮助,可以点击一下右下角的 推荐,或评论,谢谢!

posted @ 2019-09-16 16:32  DSHORE  阅读(594)  评论(0编辑  收藏  举报