Spring Data JPA一对多单向映射

x33g5p2x  于2022-10-13 转载在 Spring  
字(9.7k)|赞(0)|评价(0)|浏览(379)

在本教程中,我们将学习如何使用SpringDataJPA(Hibernate作为JPA提供者)执行一对多域模型映射。
查看Spring Data JPA one to many bidirectional mapping上的一对多双向映射教程
单向的一对多关联更简单,因为它只是定义关系的父端。在单向映射中,我们只使用@OneToMany注解。
查看我的Udemy课程学习春季数据JPA:Master Spring Data JPA with Hibernate
在关系数据库系统中,一对多关联基于外键列链接两个表,以便子表记录引用父表行的主键。

1.创建Spring Boot项目

SpringBoot提供了一个名为https://start.spring.io的web工具来快速引导应用程序。只需转到https://start.spring.io并生成一个新的spring-boot项目。

在创建Spring引导时使用以下详细信息:
**项目名称:**Spring Data jpa课程
**项目类型:**Maven
**选择依赖项:**Spring Data JPA、MySQL Driver、Lombok
**软件包名称:**net.javaguides.springboot

2.Maven依赖项

这是完整的pom.xml供您参考:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.6.1</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>net.javaguides</groupId>
	<artifactId>spring-data-jpa-course</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-data-jpa-course</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

3.配置MySQL数据库

在本例中,让我们使用MySQL数据库存储和检索数据,并使用Hibernate属性创建和删除表。

打开应用程序。属性文件,并向其中添加以下配置:

spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false
spring.datasource.username=root
spring.datasource.password=Mysql@123

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

spring.jpa.hibernate.ddl-auto = create-drop

确保在运行Spring引导应用程序之前创建一个演示数据库。
此外,根据您机器上的MySQL安装更改MySQL用户名和密码。

4.创建JPA实体

让我们在基本包“net.javaguides.springboot”中创建一个实体包。
在实体包中,创建包含以下内容的Order和OrderItems类:

Order.java

package net.javaguides.springdatajpacourse.entity;

import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name="orders")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private Long id;

    @Column(name="order_tracking_number")
    private String orderTrackingNumber;

    @Column(name="total_quantity")
    private int totalQuantity;

    @Column(name="total_price")
    private BigDecimal totalPrice;

    @Column(name="status")
    private String status;

    @Column(name="date_created")
    @CreationTimestamp
    private Date dateCreated;

    @Column(name="last_updated")
    @UpdateTimestamp
    private Date lastUpdated;

    // one to many unidirectional mapping
    // default fetch type for OneToMany: LAZY
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "order_id", referencedColumnName = "id")
    private Set<OrderItem> orderItems = new HashSet<>();

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getOrderTrackingNumber() {
        return orderTrackingNumber;
    }

    public void setOrderTrackingNumber(String orderTrackingNumber) {
        this.orderTrackingNumber = orderTrackingNumber;
    }

    public int getTotalQuantity() {
        return totalQuantity;
    }

    public void setTotalQuantity(int totalQuantity) {
        this.totalQuantity = totalQuantity;
    }

    public BigDecimal getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(BigDecimal totalPrice) {
        this.totalPrice = totalPrice;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Date getDateCreated() {
        return dateCreated;
    }

    public void setDateCreated(Date dateCreated) {
        this.dateCreated = dateCreated;
    }

    public Date getLastUpdated() {
        return lastUpdated;
    }

    public void setLastUpdated(Date lastUpdated) {
        this.lastUpdated = lastUpdated;
    }

    public Set<OrderItem> getOrderItems() {
        return orderItems;
    }

    public void setOrderItems(Set<OrderItem> orderItems) {
        this.orderItems = orderItems;
    }

    public void add(OrderItem item) {

        if (item != null) {
            if (orderItems == null) {
                orderItems = new HashSet<>();
            }

            orderItems.add(item);
           // item.setOrder(this);
        }
    }

    public BigDecimal getTotalAmount()
	{
		BigDecimal amount = new BigDecimal("0.0");
		for (OrderItem item : this.orderItems)
		{
			amount = amount.add(item.getPrice());
		}
		return amount;
	}


    @Override
    public String toString() {
        return "Order{" +
                "id=" + id +
                ", orderTrackingNumber='" + orderTrackingNumber + '\'' +
                ", totalQuantity=" + totalQuantity +
                ", totalPrice=" + totalPrice +
                ", status='" + status + '\'' +
                ", dateCreated=" + dateCreated +
                ", lastUpdated=" + lastUpdated +
                '}';
    }
}

OrderItem.java

package net.javaguides.springdatajpacourse.entity;

import javax.persistence.*;
import java.math.BigDecimal;

@Entity
@Table(name="order_items",schema = "ecommerce")
public class OrderItem {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private Long id;

    @Column(name="image_url")
    private String imageUrl;

    @Column(name = "price")
    private BigDecimal price;

    @Column(name="quantity")
    private int quantity;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public BigDecimal getPrice() {
        return this.price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }
}

5.创建Spring Data JPA存储库

接下来我们要做的是创建存储库,以便从数据库访问Order实体。

JpaRepository接口定义了实体上所有CRUD操作的方法,以及名为SimpleJpaRepresitory的JpaReppository的默认实现。
让我们在基本包“net.javaguides.springdatarest”中创建一个存储库包。
在存储库包中,创建一个包含以下内容的OrderRepository界面:

OrderRepository.java

package net.javaguides.springdatajpacourse.repository;

import net.javaguides.springdatajpacourse.entity.Order;
import org.springframework.data.jpa.repository.JpaRepository;

public interface OrderRepository extends JpaRepository<Order, Long>{
	Order findByOrderTrackingNumber(String orderTrackingNumber);
}

6.测试一对多单向映射

让我们编写JUnit测试,使用Spring Data JPA对一对多单向映射执行CRUD操作:

package net.javaguides.springdatajpacourse.repository;

import net.javaguides.springdatajpacourse.entity.Order;
import net.javaguides.springdatajpacourse.entity.OrderItem;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
public class OneToManyUnidirectionalMappingTest {

    @Autowired
    private OrderRepository orderRepository;

    @Test
    void testSaveOrder(){

        // create Order object
        Order order = new Order();

        OrderItem orderItem = new OrderItem();
        orderItem.setImageUrl("image_url.png");
        orderItem.setPrice(new BigDecimal(100));
        // add orderitem to order
        order.add(orderItem);

        OrderItem orderItem2 = new OrderItem();
        orderItem2.setImageUrl("image_url.png");
        orderItem2.setPrice(new BigDecimal(200));
        // add orderItem2 to order
        order.add(orderItem2);

        order.setOrderTrackingNumber("1000");
        order.setStatus("IN PROGRESS");
        // total amount of the order
        order.setTotalPrice(order.getTotalAmount());

        // Quantity of the order items
        order.setTotalQuantity(2);

        orderRepository.save(order);

    }

    @Test
    void testUpdateOrder(){
        Order order = orderRepository.findById(1L).get();
        order.setStatus("DELIVERED");
        orderRepository.save(order);
    }

    @Test
    void testGetAllOrders(){

        List<Order> orders = orderRepository.findAll();

        orders.forEach((o) -> {

            System.out.println("order id :: " + o.getId());

            o.getOrderItems().forEach((orderItem -> {
                System.out.println("orderItem :: " + orderItem.getId());
            }));
        });
    }

    @Test
    void testFindByOrderTrackingNumber(){

        Order order = orderRepository.findByOrderTrackingNumber("1000");

        // add fetch type as EAGER
//        order.getOrderItems().forEach((o) -> {
//            System.out.println(o.getId());
//        });
    }

    @Test
    void testDeleteOrder(){

        orderRepository.deleteById(1L);
    }
}

保存订单还将保存关联的订单项目:

@Test
    void testSaveOrder(){

        // create Order object
        Order order = new Order();

        OrderItem orderItem = new OrderItem();
        orderItem.setImageUrl("image_url.png");
        orderItem.setPrice(new BigDecimal(100));
        // add orderitem to order
        order.add(orderItem);

        OrderItem orderItem2 = new OrderItem();
        orderItem2.setImageUrl("image_url.png");
        orderItem2.setPrice(new BigDecimal(200));
        // add orderItem2 to order
        order.add(orderItem2);

        order.setOrderTrackingNumber("1000");
        order.setStatus("IN PROGRESS");
        // total amount of the order
        order.setTotalPrice(order.getTotalAmount());

        // Quantity of the order items
        order.setTotalQuantity(2);

        orderRepository.save(order);

    }

更新订单操作

@Test
    void testUpdateOrder(){
        Order order = orderRepository.findById(1L).get();
        order.setStatus("DELIVERED");
        orderRepository.save(order);
    }

“获取所有订单”还将获取其关联的订单项目:

@Test
    void testGetAllOrders(){

        List<Order> orders = orderRepository.findAll();

        orders.forEach((o) -> {

            System.out.println("order id :: " + o.getId());

            o.getOrderItems().forEach((orderItem -> {
                System.out.println("orderItem :: " + orderItem.getId());
            }));
        });
    }

删除订单还将删除其关联的订单项目:

@Test
    void testDeleteOrder(){

        orderRepository.deleteById(1L);
    }

相关文章