【问题标题】:Why do I have to input ID (PK) - problem with auto generating ID为什么我必须输入 ID (PK) - 自动生成 ID 的问题
【发布时间】:2019-04-22 16:56:39
【问题描述】:

我正在我的图书出租中创建出租图书的方法。它看起来像这样:

@PostMapping("/book")
public void purchaseBook(@RequestParam("userID") int userID, @RequestParam("bookID") int bookID) {
    bookRentalService.rentBook(userID, bookID);
}

输入 userID 和 bookID 后,book 如果可用,则添加到 BookRentalDB。

我这样制作的表之间的关系:

出租实体

package bookrental.model.book;

import bookrental.model.account.User;
import lombok.*;

import javax.persistence.*;

@Entity
@Getter
@Setter
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor
public class BookRentals {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @OneToOne
    private Book book;
    @OneToOne
    private User user;
}

我在服务中创建此实体(BookRentals)的对象时遇到问题。它需要包含Book 的对象和User 的对象。我为这个对象创建了构造函数,只有bookID 用于BookuserID 用于User。在prepareBookToRent 中,我也要求输入BookRentals 类的ID。在那种情况下,我不能创建它的对象。它不应该自动生成吗?我应该怎么做才能让它发挥作用。

package bookrental.service.book;

import bookrental.model.account.User;
import bookrental.model.book.Book;
import bookrental.model.book.BookRentals;
import bookrental.repository.book.BookRepository;
import bookrental.repository.book.BookRentalsRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookRentalService {

    private final BookRepository bookRepository;
    private final BookRentalsRepository bookRentalsRepository;

    @Autowired
    public BookRentalService(BookRepository bookRepository, BookRentalsRepository bookRentalsRepository) {
        this.bookRepository = bookRepository;
        this.bookRentalsRepository = bookRentalsRepository;
    }

    public void rentBook(int userID, int bookID) {
        if (bookRepository.doesBookExistsWithGivenID(bookID)) {
            Book bookToRent = bookRepository.findOne(bookID);
            if (bookToRent.isAvailable()) {
                updateBookAvailabilityAndSaveToDb(bookToRent);
                BookRentals preparedBookToRent = prepareBookToRent(userID, bookID);
                bookRentalsRepository.save(preparedBookToRent);
            } else {
                throw new IllegalArgumentException("Book is no available");
            }
        }
        throw new IllegalArgumentException("Book does not exist!");
    }


    private BookRentals prepareBookToRent(int userID, int bookID) {
        return new BookRentals(new Book(bookID),new User(userID)); // here im asked to input ID, too
    }

    private void updateBookAvailabilityAndSaveToDb(Book bookToRent) {
        bookToRent.setAvailable(false);
        bookRepository.save(bookToRent);
    }
}

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.book.rental.piotrek</groupId>
    <artifactId>BookRental</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>



    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.22</version>
        </dependency>
    </dependencies>

</project>

Staktrace

C:\Users\Admin\IdeaProjects\BookRental\src\main\java\bookrental\service\book\BookRentalService.java
Error:(39, 16) java: no suitable constructor found for BookRentals(bookrental.model.book.Book,bookrental.model.account.User)
    constructor bookrental.model.book.BookRentals.BookRentals(int,bookrental.model.book.Book,bookrental.model.account.User) is not applicable
      (actual and formal argument lists differ in length)
    constructor bookrental.model.book.BookRentals.BookRentals() is not applicable
      (actual and formal argument lists differ in length)

正如我上面所说,就是这样:

【问题讨论】:

  • 请发布错误堆栈跟踪。还添加有关数据库类型和版本、Spring Boot 版本、Java 版本、JPA 提供程序的信息。
  • @EugenCovaci 更新了 pom.xml 和stratrace。
  • 您的问题与JPA自动生成的id无关,与Lombok使用不当有关。
  • @EugenCovaci 我应该从 costructor 中排除 ID,正如 Asnswer 中的 Sarief 所说的那样吗?
  • @EugenCovaci 然后查看更新的答案。没有注意到映射类上的 OneToOne 注释。这没有意义,所以我的大脑忽略了它

标签: java spring-boot primary-key crud


【解决方案1】:

你错了,你创建了所有的 args 构造函数。你有3个属性。这意味着,所有 args 构造函数都有 3 个参数而不是 2 个。

只需创建自定义构造函数。

public BookRentals (Book book, User user) {
// logic
}

ps:为什么不能从所有 args 中排除某些参数:Java Lombok: Omitting one field in @AllArgsConstructor?

upd:cmets 正在陈述一些疯狂的事情。因此,如果您一对一,请直接在实体上使用注释。如果您有多对多,请考虑 OneToMany,因为让多个用户租用同一本书是不现实的。

表格设计参考:How to implement one-to-one, one-to-many and many-to-many relationships while designing tables?

【讨论】:

  • ID会自动生成吗?
  • Id,如果注解得当,保存实体后会生成
  • 我已经正确注释了,对吧? :D 我为什么要考虑@OneToMany - 一本书只能由一个用户租用一次。
  • @pipilam 至于为什么......这是惯例。此约定不仅由您使用,而且由您使用的框架使用。按照公认的约定进行设计可以帮助您轻松地与这些框架集成。 QueryDsl 和 Spring Data 可以基于这些设计生成元实体,其他开发人员立即知道事情是如何工作的,等等。
  • 好吧,我试图理解链接中的概念。我想你不明白我是怎么做到的。我在图片上说明了它。我创建了 3 个实体 - 一个用于书籍,一个用于用户,一个用于出租。我需要 3 张桌子。我需要 OneToOne 关系。不幸的是,我不明白你的意思。我想我会像我写的那样离开。
猜你喜欢
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
  • 2014-05-12
  • 1970-01-01
  • 2018-11-28
  • 1970-01-01
  • 2013-10-05
  • 2017-07-31
相关资源
最近更新 更多