Hibernate03-单向 简单一对多关系映射
Hibernate    2017-11-19 01:24:06    345    0    0
acme   Hibernate

这一章讲的是简单的多对一关系映射。

1.首先是开发环境,使用Maven版本为3.5,jdk版本为9.0.1,Hibernate版本为5.0.1Final,数据库为MySQL5.7.20

2.配置Maven的pom.xml文件,由于我当前的jdk版本以及Hibernate版本所以依赖如配置文件中所列出。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
<groupId>cc.acme_me.hibernate</groupId>
 <artifactId>Hibernate03</artifactId>
 <version>1.0-SNAPSHOT</version>
 <name>Hibernate01</name>
<dependencies>
<!-- junit -->
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>4.12</version>
 <scope>test</scope>
 </dependency>
<!-- mysql-connector-java -->
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>6.0.6</version>
 </dependency>
<dependency>
 <groupId>org.hibernate</groupId>
 <artifactId>hibernate-core</artifactId>
 <version>5.2.12.Final</version>
 </dependency>
<dependency>
 <groupId>antlr</groupId>
 <artifactId>antlr</artifactId>
 <version>2.7.7</version>
 </dependency>
<dependency>
 <groupId>com.fasterxml</groupId>
 <artifactId>classmate</artifactId>
 <version>1.3.4</version>
 </dependency>
<dependency>
 <groupId>dom4j</groupId>
 <artifactId>dom4j</artifactId>
 <version>1.6.1</version>
 </dependency>
<dependency>
 <groupId>org.hibernate.common</groupId>
 <artifactId>hibernate-commons-annotations</artifactId>
 <version>5.0.1.Final</version>
 </dependency>
<dependency>
 <groupId>org.jboss.logging</groupId>
 <artifactId>jboss-logging</artifactId>
 <version>3.3.0.Final</version>
 </dependency>
<dependency>
 <groupId>org.hibernate.javax.persistence</groupId>
 <artifactId>hibernate-jpa-2.1-api</artifactId>
 <version>1.0.0.Final</version>
 </dependency>
<dependency>
 <groupId>org.javassist</groupId>
 <artifactId>javassist</artifactId>
 <version>3.20.0-GA</version>
 </dependency>
<dependency>
 <groupId>org.jboss</groupId>
 <artifactId>jandex</artifactId>
 <version>2.0.3.Final</version>
 </dependency>
<dependency>
 <groupId>org.jboss.logging</groupId>
 <artifactId>jboss-logging</artifactId>
 <version>3.3.0.Final</version>
 </dependency>
<dependency>
 <groupId>org.jboss.spec.javax.transaction</groupId>
 <artifactId>jboss-transaction-api_1.2_spec</artifactId>
 <version>1.0.1.Final</version>
 </dependency>
<dependency>
 <groupId>com.sun.xml.bind</groupId>
 <artifactId>jaxb-core</artifactId>
 <version>2.3.0</version>
 </dependency>
 <dependency>
 <groupId>javax.xml.bind</groupId>
 <artifactId>jaxb-api</artifactId>
 <version>2.3.0</version>
 </dependency>
 <dependency>
 <groupId>com.sun.xml.bind</groupId>
 <artifactId>jaxb-impl</artifactId>
 <version>2.3.0</version>
 </dependency>
 <dependency>
 <groupId>javax.activation</groupId>
 <artifactId>activation</artifactId>
 <version>1.1.1</version>
 </dependency>
 </dependencies>
</project>​

  3.Hibernate的全局配置文件hibernate.cfg.xml,这一章我们同样还是使用注解

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
 "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory>
 <!--数据库连接设置-->
 <property name="connection.username">root</property>
 <property name="connection.password">root</property>
 <property name="connection.url">jdbc:mysql://localhost:3306/db_hibernate</property>
 <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
 <!--数据库方言-->
 <property name="dialect">org.hibernate.dialect.MySQL57Dialect</property>
 <!--显示sql语句-->
 <property name="show_sql">true</property>
 <!--格式化sql语句-->
 <property name="format_sql">true</property>
 <!--设置ddl 根据设置自动更新表结构 包括添加删除表 更新表结构-->
 <property name="hbm2ddl.auto">create-drop</property>
<!--告诉Hibernate映射的实体类-->
 <mapping class="cc.acme_me.model.Student"/>
 <mapping class="cc.acme_me.model.Group"/>
 </session-factory>
</hibernate-configuration>​

 4.新建两个实体类Student和Group并且表示一对多的关系

package cc.acme_me.model;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
@Entity
@Table(name = "t_group")
public class Group {
@Column(name = "groupID")
 @Id
 @GenericGenerator(name = "native", strategy = "native")//定义策略然后下面使用
 @GeneratedValue(generator = "native")
 private int groupID;//组ID
@Column(name = "groupName")
 private String groupName;//组名
public String getGroupName() {
 return groupName;
 }
public void setGroupName(String groupName) {
 this.groupName = groupName;
 }
public int getGroupID() {
 return groupID;
 }
public void setGroupID(int groupID) {
 this.groupID = groupID;
 }
@Override
 public String toString() {
 return "Group{" +
 "groupID=" + groupID +
 ", groupName='" + groupName + '\'' +
 '}';
 }
}​

通常,我们在一对多的关系中,在多的一方增加少的一方的关联关系。

这也是这一章所讲到的注解@ManyToOne@JoinColumn,当然,这两个注解还有属性,我在后续的章节中慢慢增加。JoinColumn的name属性便是外键的列名

package cc.acme_me.model;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
@Entity
@Table(name = "t_student")
public class Student {
@Id
 @GenericGenerator(name = "native", strategy = "native")
 @GeneratedValue(generator = "native")
 private long id;//作为主键
@Column(name = "studentname")
 private String name;//姓名
@Column(name = "studentage")
 private int age;//年龄
@ManyToOne
 @JoinColumn(name = "groupID")
 private Group group;//所属组
public long getId() {
 return id;
 }
public void setId(long id) {
 this.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;
 }
public Group getGroup() {
 return group;
 }
public void setGroup(Group group) {
 this.group = group;
 }
@Override
 public String toString() {
 return "Student{" +
 "id=" + id +
 ", name='" + name + '\'' +
 ", age=" + age +
 ", group=" + group +
 '}';
 }
}​

5.接下来便是使用Junit测试进行测试

首先贴上工具类(其实是偷懒)

package cc.acme_me.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;
public class SessionUtils {
public static Session openSession() {
 ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
 SessionFactory sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
 return sessionFactory.openSession();
 }
}​

测试类

package cc.acme_me.test;
import cc.acme_me.model.Group;
import cc.acme_me.model.Student;
import cc.acme_me.utils.SessionUtils;
import org.hibernate.Session;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class TestStudent {
 private Session session = null;
@Before
 public void openSession() {
 session = SessionUtils.openSession();
 session.beginTransaction();
 }
@After
 public void closeSession() {
 session.getTransaction().commit();
 session.close();
 }
@Test
 public void testAdd() {
//创建组并保存
 Group group = new Group();
 group.setGroupName("Group 1");
 session.save(group);//因为没有配置cascade,所以需要手动保存一下组
//组里面添加一个学生
 Student student = new Student();
 student.setAge(18);
 student.setName("Admin");
 student.setGroup(group);
 session.save(student);
//组里面再添加一个学生
 student = new Student();
 student.setName("Admin2");
 student.setAge(20);
 session.save(student);
 student.setGroup(group);
 session.save(student);
 }
}​

首先是添加方法,同时也看看Hibernate打印出来的sql语句。

Hibernate: 
 insert 
 into
 t_group
 (groupName) 
 values
 (?)
Hibernate: 
 insert 
 into
 t_student
 (studentage, groupID, studentname) 
 values
 (?, ?, ?)
Hibernate: 
 insert 
 into
 t_student
 (studentage, groupID, studentname) 
 values
 (?, ?, ?)
Hibernate: 
 update
 t_student 
 set
 studentage=?,
 groupID=?,
 studentname=? 
 where
 id=?​

插入成功后我们也可以在表中查看到刚刚插入的数据,同时也可以查看一下表的结构。

当然,也可以使用show create table 'tb_name'来查看表创建的语句。

上面展示了表内的数据,接着就试试查询。

@Test
 public void testFind() {
 Student student = session.get(Student.class, 1L);
 System.out.println(student);
 }​

可以看到控制台的sql语句滚动以及打印出来的student信息。

而且同样也可以查询Group的内容。

@Test
 public void testFindGroup() {
 Group group = session.get(Group.class, 1);
 System.out.println(group);
 }​

接下来的update和delete便不再一一列出,因为这并没有什么意思。

我这个时候对Group操作,我要删除它。但是Group的主键是Student的外键,删除时Group的时候Hibernate会如何出来Student表内的数据?是将外键值置为为空(0)?还是同事删除Group内的Student的数据?

@Test
 public void testDeleteGroup() {
 Group group = session.get(Group.class, 1);
 session.delete(group);
 }​

执行这个操作,结局红红的异常,并且,异常会明确的告诉你:java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`db_hibernate`.`t_student`, CONSTRAINT `FKeyqu03o2m70hvm5iymc7cj5kd` FOREIGN KEY (`groupID`) REFERENCES `t_group` (`groupID`))

这个时候肯定有人想说,我就是想要干掉Student内的数据,级联操作,全部给我干。

这个就放到后面去配置cascade来实现。

Pre: 搭建PPTP VPN

Next: Hibernate02-简单的注解操作

345
Table of content