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 packagecom.shore.entity;2
3 importjava.io.Serializable;4
5 importjavax.persistence.Entity;6
7 /**
8 *@authorDSHORE/2019-9-169 *10 */
11
12 @Entity13 public class StudentPK implementsSerializable {14 private static final long serialVersionUID = -2060041603022800114L; //序列化15
16 //name+address作为联合主键
17 privateString name;18 privateString address;19
20 publicStudentPK() {21 super();22 }23 publicStudentPK(String name, String address) {24 super();25 this.name =name;26 this.address =address;27 }28
29 publicString getName() {30 returnname;31 }32 public voidsetName(String name) {33 this.name =name;34 }35
36 publicString getAddress() {37 returnaddress;38 }39 public voidsetAddress(String address) {40 this.address =address;41 }42
43 //联合主键类序列化,重写equals和hashCode方法
44 @Override45 public booleanequals(Object object) {46 //instanceof——判断左边对象是否为右边对象的实例
47 if (object instanceofStudentPK) {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 @Override58 public inthashCode() {59 return this.name.hashCode();60 }61 }
Student 实体类:
1 packagecom.shore.entity;2
3 importjava.io.Serializable;4
5 importjavax.persistence.EmbeddedId;6 importjavax.persistence.Entity;7
8 importorg.hibernate.annotations.Type;9
10 /**
11 *@authorDSHORE/2019-9-1612 *13 */
14
15 @Entity16 public class Student implementsSerializable {17 //对应的Student对象类建议也要序列化,但是可以不重写equals和hashCode方法
18 private static final long serialVersionUID = -2924879320015689901L;19
20 private StudentPK keys;//联合主键 别名
21 privateBoolean sex;22 privateString hobby;23
24 publicStudent() {25 super();26 }27 publicStudent(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 publicStudentPK getKeys() {36 returnkeys;37 }38 public voidsetKeys(StudentPK keys) {39 this.keys =keys;40 }41
42 @Type(type = "yes_no") //数据库中,会以Y/N的形式插入到sex字段中
43 publicBoolean getSex() {44 returnsex;45 }46 public voidsetSex(Boolean sex) {47 this.sex =sex;48 }49
50 publicString getHobby() {51 returnhobby;52 }53 public voidsetHobby(String hobby) {54 this.hobby =hobby;55 }56 }
1.4.2、创建hibernate.cfg.xml配置文件
1 <?xml version='1.0' encoding='utf-8'?>
2 "-//Hibernate/Hibernate Configuration DTD 3.0//EN"4 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
5
6
7
8
9 com.mysql.jdbc.Driver
10 jdbc:mysql://localhost:3306/school
11 root
12 123456
13
14 org.hibernate.dialect.MySQLDialect
15 org.hibernate.cache.NoCacheProvider
16 true
17 create
18
19
20
21
22
联合主键,MySQL数据库的写法:(本文不需要手动创建数据表,是自动创建的,下面的MySQL建表脚本,仅提供参考)
1 CREATE TABLEstudent(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 packagecom.shore.test;2
3 importorg.hibernate.Session;4 importorg.hibernate.SessionFactory;5 importorg.hibernate.Transaction;6 importorg.hibernate.cfg.AnnotationConfiguration;7 importorg.junit.AfterClass;8 importorg.junit.BeforeClass;9 importorg.junit.Test;10
11 importcom.shore.entity.Student;12 importcom.shore.entity.StudentPK;13
14 /**
15 *@authorDSHORE/2019-9-1616 *17 */
18 public classCompositeKeyTest {19 public static SessionFactory sessionFactory = null;20 public static Session session = null;21
22 @BeforeClass23 public static voidbuildSessionFactory() {24 //联合主键之Annotation实现,用的是AnnotationConfiguration方法
25 sessionFactory = newAnnotationConfiguration().configure().buildSessionFactory();26 }27
28 @AfterClass29 public static voidclose() {30 session.close();31 sessionFactory.close();32 }33
34 @Test35 public voidtest() {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 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
5
6
7
8
9
10
11
12
13
14
15
2.3、最后在hibernate.cfg.xml配置文件中引入“student.hbm.xml”文件即可
1 <?xml version='1.0' encoding='utf-8'?>2/p>
3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
4 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">5
6789com.mysql.jdbc.Driver10jdbc:mysql://localhost:3306/school11root1212345613
14org.hibernate.dialect.MySQLDialect15org.hibernate.cache.NoCacheProvider16true17create18
19202122
2.4、还有sessionFactory创建方式不一样:
1 packagecom.shore.test;2
3 importorg.hibernate.Session;4 importorg.hibernate.SessionFactory;5 importorg.hibernate.Transaction;6 importorg.hibernate.cfg.AnnotationConfiguration;7 importorg.junit.AfterClass;8 importorg.junit.BeforeClass;9 importorg.junit.Test;10
11 importcom.shore.entity.Student;12 importcom.shore.entity.StudentPK;13
14 /**
15 *@authorDSHORE/2019-9-1616 *17 */
18 public classCompositeKeyTest2 {19 public static SessionFactory sessionFactory = null;20 public static Session session = null;21
22 @BeforeClass23 public static voidbuildSessionFactory() {24 //联合主键之xml实现,用的是Configuration()方法
25 sessionFactory = new Configuration().configure().buildSessionFactory(); //之前用的是:AnnotationConfiguration()
26 }27
28 @AfterClass29 public static voidclose() {30 session.close();31 sessionFactory.close();32 }33
34 @Test35 public voidtest() {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 }