JPA(五):映射关联关系------映射单向多对一的关联关系

时间:2023-03-09 01:42:15
JPA(五):映射关联关系------映射单向多对一的关联关系

映射单向多对一的关联关系

新建Customer.java:

package com.dx.jpa.singlemanytoone;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient; @Entity
@Table(name = "jpa_customer")
public class Customer {
private Integer id;
private String fullName;
private Integer age;
private Date birth;
private Date createDate; @Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} @Column(name = "FULL_NAME", length = 64, nullable = false)
public String getFullName() {
return fullName;
} public void setFullName(String fullName) {
this.fullName = fullName;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} @Temporal(TemporalType.DATE)
public Date getBirth() {
return birth;
} public void setBirth(Date birth) {
this.birth = birth;
} @Temporal(TemporalType.TIMESTAMP)
public Date getCreateDate() {
return createDate;
} public void setCreateDate(Date createDate) {
this.createDate = createDate;
} // 帮助方法,不希望保存到数据库,但是需要动态获取Customer对象的属性。
@Transient
public String getCustomerInfo() {
return "username:" + fullName + ",age:" + age;
}
}

Order.java:

package com.dx.jpa.singlemanytoone;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table; @Entity
@Table(name = "jpa_order")
public class Order {
private Integer id;
private String name;
private Customer customer; @Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} // @JoinColumn来映射外键
// @ManyToOne映射单项一对多映射关系
@JoinColumn(name = "CUSTOMER_ID")
@ManyToOne()
public Customer getCustomer() {
return customer;
} public void setCustomer(Customer customer) {
this.customer = customer;
} }

Client.java测试类:

package com.dx.jpa.singlemanytoone;

import java.util.Date;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence; import org.hamcrest.CustomTypeSafeMatcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; public class Client {
private String persistenceUnitName = "Jpa-helloword";
private EntityManagerFactory entityManagerFactory = null;
private EntityManager entityManager = null;
private EntityTransaction entityTransaction = null; @Before
public void init() {
// 1.创建EntityManagerFactory
entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnitName);
// 2.创建EntityManager
entityManager = entityManagerFactory.createEntityManager();
// 3.开始事务
entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
} @After
public void destory() {
// 5.提交事务
entityTransaction.commit(); // 6.关闭EntityManager
entityManager.close();
// 7.关闭EnityManagerFactory
entityManagerFactory.close();
}
}

将Customer,Person添加到jpa配置文件persistence.xml中:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="Jpa-helloword"
transaction-type="RESOURCE_LOCAL">
<!-- 配置使用什么 ORM 产品来作为 JPA 的实现 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- 添加持久化类 -->
<class>com.dxsoft.jpa.helloword.Person</class>
<class>com.dx.jpa.singlemanytoone.Customer</class>
<class>com.dx.jpa.singlemanytoone.Order</class>
<properties>
<!-- 数据库的相关配置 -->
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/jpa" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="root" />
<!-- 指定方言
MySQL org.hibernate.dialect.MySQLDialect
MySQL with InnoDB org.hibernate.dialect.MySQLInnoDBDialect
MySQL with MyISAM org.hibernate.dialect.MySQLMyISAMDialect
MySQL5 org.hibernate.dialect.MySQL5Dialect
MySQL5 with InnoDB org.hibernate.dialect.MySQL5InnoDBDialect
-->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<!--
create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。<br>
create-drop :每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。<br>
update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。<br>
validate :每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。 <br>
-->
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>

执行初始化时,创建表打印语句如下:

Hibernate: 

    create table jpa_customer (
id integer not null,
age integer,
birth date,
createDate datetime,
FULL_NAME varchar(64) not null,
primary key (id)
) engine=InnoDB
Hibernate: create table jpa_order (
id integer not null,
name varchar(255),
CUSTOMER_ID integer,
primary key (id)
) engine=InnoDB
Hibernate: alter table jpa_order
add constraint FK7glkngwj74nr8h2amofkp1fjd
foreign key (CUSTOMER_ID)
references jpa_customer (id)

此时查看表,发现jpa_order表上新建了外键:

JPA(五):映射关联关系------映射单向多对一的关联关系

测试添加:

添加测试函数:

    @Test
public void testPersist() {
Customer customer = new Customer();
customer.setFullName("AA");
customer.setAge(26);
customer.setBirth(new Date());
customer.setCreateDate(new Date()); Order order1 = new Order();
order1.setName("O-AA-01");
order1.setCustomer(customer); Order order2 = new Order();
order2.setName("O-AA-02");
order2.setCustomer(customer); entityManager.persist(customer);
entityManager.persist(order1);
entityManager.persist(order2);
}

此时打印语句为:

Hibernate:
select
next_val as id_val
from
hibernate_sequence for update Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
Hibernate:
select
next_val as id_val
from
hibernate_sequence for update Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
Hibernate:
select
next_val as id_val
from
hibernate_sequence for update Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
Hibernate:
insert
into
jpa_customer
(age, birth, createDate, FULL_NAME, id)
values
(?, ?, ?, ?, ?)
Hibernate:
insert
into
jpa_order
(CUSTOMER_ID, name, id)
values
(?, ?, ?)
Hibernate:
insert
into
jpa_order
(CUSTOMER_ID, name, id)
values
(?, ?, ?)

修改customer,order1,order2添加顺序:

    @Test
public void testPersist() {
Customer customer = new Customer();
customer.setFullName("BB");
customer.setAge(26);
customer.setBirth(new Date());
customer.setCreateDate(new Date()); Order order1 = new Order();
order1.setName("O-BB-01");
order1.setCustomer(customer); Order order2 = new Order();
order2.setName("O-BB-02");
order2.setCustomer(customer); entityManager.persist(order1);
entityManager.persist(order2);
entityManager.persist(customer);
}

执行打印sql语句如下:

Hibernate:
select
next_val as id_val
from
hibernate_sequence for update Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
Hibernate:
select
next_val as id_val
from
hibernate_sequence for update Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
Hibernate:
select
next_val as id_val
from
hibernate_sequence for update Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
Hibernate:
insert
into
jpa_order
(CUSTOMER_ID, name, id)
values
(?, ?, ?)
Hibernate:
insert
into
jpa_order
(CUSTOMER_ID, name, id)
values
(?, ?, ?)
Hibernate:
insert
into
jpa_customer
(age, birth, createDate, FULL_NAME, id)
values
(?, ?, ?, ?, ?)
Hibernate:
update
jpa_order
set
CUSTOMER_ID=?,
name=?
where
id=?
Hibernate:
update
jpa_order
set
CUSTOMER_ID=?,
name=?
where
id=?

从打印信息中可以看出,此时是先插入的order,之后在修改其customer_id。比起之前的那种写法多出来了两次修改。

测试查询:

添加测试查询函数:

    @Test
public void testSelect() {
Order order = entityManager.find(Order.class, 3);
System.out.println(order.getName());
//System.out.println(order.getCustomer().getFullName());
}

此时执行打印sql语句为:

Hibernate:
select
order0_.id as id1_1_0_,
order0_.CUSTOMER_ID as CUSTOMER3_1_0_,
order0_.name as name2_1_0_,
customer1_.id as id1_0_1_,
customer1_.age as age2_0_1_,
customer1_.birth as birth3_0_1_,
customer1_.createDate as createDa4_0_1_,
customer1_.FULL_NAME as FULL_NAM5_0_1_
from
jpa_order order0_
left outer join
jpa_customer customer1_
on order0_.CUSTOMER_ID=customer1_.id
where
order0_.id=?

从sql语句可以看出即使不插叙customer信息,也会使用left outer join把customer信息给关联出来。

修改Order的getCustomer方法的属性:

JPA(五):映射关联关系------映射单向多对一的关联关系

修改Order属性为:

JPA(五):映射关联关系------映射单向多对一的关联关系

重新测试查询:

    @Test
public void testSelect() {
Order order = entityManager.find(Order.class, 2);
System.out.println("------------------------");
System.out.println(order.getName());
System.out.println("------------------------");
System.out.println(order.getCustomer().getFullName());
System.out.println("------------------------");
}

打印sql语句为:

Hibernate:
select
order0_.id as id1_1_0_,
order0_.CUSTOMER_ID as CUSTOMER3_1_0_,
order0_.name as name2_1_0_
from
jpa_order order0_
where
order0_.id=?
------------------------
O-BB-02
------------------------
Hibernate:
select
customer0_.id as id1_0_0_,
customer0_.age as age2_0_0_,
customer0_.birth as birth3_0_0_,
customer0_.createDate as createDa4_0_0_,
customer0_.FULL_NAME as FULL_NAM5_0_0_
from
jpa_customer customer0_
where
customer0_.id=?
BB
------------------------

查询修改:

添加修改测试:

    @Test
public void testUpdate() {
Order order = entityManager.find(Order.class, 1);
order.setName("O-BBB-01");
order.getCustomer().setFullName("BBB");
}

打印执行sql:

Hibernate:
select
order0_.id as id1_1_0_,
order0_.CUSTOMER_ID as CUSTOMER3_1_0_,
order0_.name as name2_1_0_
from
jpa_order order0_
where
order0_.id=?
Hibernate:
select
customer0_.id as id1_0_0_,
customer0_.age as age2_0_0_,
customer0_.birth as birth3_0_0_,
customer0_.createDate as createDa4_0_0_,
customer0_.FULL_NAME as FULL_NAM5_0_0_
from
jpa_customer customer0_
where
customer0_.id=?
Hibernate:
update
jpa_order
set
CUSTOMER_ID=?,
name=?
where
id=?
Hibernate:
update
jpa_customer
set
age=?,
birth=?,
createDate=?,
FULL_NAME=?
where
id=?

查询删除:

测试删除多的一端:

    @Test
public void testRemove() {
Order order = entityManager.find(Order.class, 1);
entityManager.remove(order);
}

执行打印语句:

Hibernate:
select
order0_.id as id1_1_0_,
order0_.CUSTOMER_ID as CUSTOMER3_1_0_,
order0_.name as name2_1_0_
from
jpa_order order0_
where
order0_.id=?
Hibernate:
delete
from
jpa_order
where
id=?

删除一的一端,此时其在多的一端还对应的有数据记录:

JPA(五):映射关联关系------映射单向多对一的关联关系

JPA(五):映射关联关系------映射单向多对一的关联关系

执行测试函数:

    @Test
public void testRemove() {
Customer customer = entityManager.find(Customer.class, 3);
entityManager.remove(customer);
}

提示删除失败:

JPA(五):映射关联关系------映射单向多对一的关联关系

再次修改,将多一端的对应的数据也删除后,再次尝试删除:

    @Test
public void testRemove() {
Order order = entityManager.find(Order.class, 2);
entityManager.remove(order); Customer customer = entityManager.find(Customer.class, 3);
entityManager.remove(customer);
}

此时提示删除成功。