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