当前位置: 首页 > 知识库问答 >
问题:

如何使用Spring启动/百里叶从数据库相关的许多关系中从交叉表中获取数据

郎子平
2023-03-14

有两个表Books和User。它们通过多对多关系连接,并在它们之间使用列book_id、reader_id、开始日期和结束日期的交叉表。我需要将此表中的数据User.login、Books.title、start_date和end_date。如果我有以下实体,如何从此表中获取数据:

图书实体:

@Entity
@Table(name = "books")
public class Book {

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

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

@Column(name = "publishing_year")
private Integer publishingYear;

@Column(name = "sell_cost")
private BigDecimal sellCost;

@Column(name = "rent_cost")
private BigDecimal rentCost;

@Column(name = "amount")
private Integer amount;

//=======Relationships=======

@ManyToMany(cascade = {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH,CascadeType.REMOVE})
@JoinTable(name = "rented_books",
joinColumns = @JoinColumn(name = "book_id"),
inverseJoinColumns = @JoinColumn(name = "reader_id"))
private List<User> usersRented;
}

用户实体:

@Entity
@Table(name = "users")
public class User {

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

@Column(name = "username")
private String login;

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

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

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

@Column(name = "wallet")
private Integer wallet;

@Column(name = "enabled")
private boolean enabled;

//=======Relationships=======

@ManyToMany(mappedBy = "usersRented")
private List<Book> rentedBooks;

图书库

@Repository
public interface BookRepository  extends CrudRepository<Book,Long> {

@Query(value = "SELECT b.title,rb.start_date,rb.expiration_date FROM books b INNER JOIN rented_books rb ON rb.book_id = b.id INNER JOIN users u ON u.id = rb.reader_id WHERE u.id = ?1",nativeQuery = true)
Page<Book> findAllRentedBookByUser(Long id, Pageable pageable);

}

但此查询不起作用,抛出此错误:

java.sql.SQLException:未找到列id。

尽管在 DBMS 中此查询工作正常

共有1个答案

宋鸿德
2023-03-14

您将返回 Book 实体,因此需要为该实体选择所有字段。不能返回部分填充的实体,因为 JPA 不支持从本机查询填充部分实体。
根据 JPA 规范:

3.10.16.1从本机查询返回托管实体


当要从本机查询返回实体时,SQL语句应该选择映射到实体对象的所有列。这应该包括相关实体的外键列。当可用数据不足时获得的结果是未定义的

正确查询示例:

@Repository
public interface BookRepository  extends CrudRepository<Book,Long> {
    @Query(value = "SELECT b.* FROM books b INNER JOIN rented_books rb ON rb.book_id = b.id INNER JOIN users u ON u.id = rb.reader_id WHERE u.id = ?1", nativeQuery = true)
    Page<Book> findAllRentedBookByUser(Long id, Pageable pageable);
}

如果要返回自定义列集,则需要创建一个额外的简单POJO类并为其定义映射
示例:如何修复Spring boot中Nativequery中的转换错误

1.创建自定义POJO类

import java.util.Date;

public class BookDetails {
   private String title;
   private Date start_date;
   private Date expiration_date;

   public BookDetails(String title, Date start_date, Date expiration_date) {
        this.title = title;
        this.start_date = start_date;
        this.expiration_date = expiration_date;
    }

    public String getTitle() {
        return this.title;
    }

    public Date getStart_date() {
        return this.start_date;
    }

    public Date getExpiration_date() {
        return this.expiration_date;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setStart_date(Date start_date) {
        this.start_date = start_date;
    }

    public void setExpiration_date(Date expiration_date) {
        this.expiration_date = expiration_date;
    }
}

2. 为 POJO 类定义@NamedNativeQuery和映射

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

@Entity
@Table(name = "books")
@NamedNativeQuery(name ="BookDetailsByUser",
        query =
                " SELECT b.title, rb.start_date, rb.expiration_date " +
                " FROM books b INNER JOIN rented_books rb ON rb.book_id = b.id INNER JOIN users u ON u.id = rb.reader_id " +
                " WHERE u.id = ?1 ",
        resultSetMapping = "BookDetailsMapping"
)
@SqlResultSetMapping(name="BookDetailsMapping",
        classes = {
                @ConstructorResult(targetClass = BookDetails.class,
                        columns = {@ColumnResult(name = "title"),
                                   @ColumnResult(name = "start_date"),
                                   @ColumnResult(name = "expiration_date")
                        })
        })
public class Book {

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

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

    @Column(name = "publishing_year")
    private Integer publishingYear;

    @Column(name = "sell_cost")
    private BigDecimal sellCost;

    @Column(name = "rent_cost")
    private BigDecimal rentCost;

    @Column(name = "amount")
    private Integer amount;

//=======Relationships=======

    @ManyToMany(cascade = {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH,CascadeType.REMOVE})
    @JoinTable(name = "rented_books",
            joinColumns = @JoinColumn(name = "book_id"),
            inverseJoinColumns = @JoinColumn(name = "reader_id"))
    private List<User> usersRented;
}

3.在存储库中使用命名查询

@Repository
public interface BookRepository  extends CrudRepository<Book,Long> {
    @Query(name = "BookDetailsByUser", nativeQuery = true)
    Page<BookDetails> findBookDetailsByUser(Long id, Pageable pageable);
}
 类似资料:
  • 我正在构建一个小应用程序,以便在Laravel7中试验多对多关系。此应用程序涉及项目和用户(多对多)。 经过身份验证的用户可以创建新项目。每个项目都有自己的页面。在项目页面上,将呈现一个列表,其中包含作为该项目成员的每个用户的名称,在每个名称旁边是一个按钮,该按钮将从该项目中删除特定用户/成员。 现在,我被困在“删除用户”功能上。我不明白如何获取列表中每个用户的id,并将其传递给将“分离”多对多关

  • 我有两个表hesk\u用户,如下所示。 @实体@表(name=“hesk\u users”)公共类UserHesk{ } @实体@表(name=“user”)公共类用户实现可序列化{ } 我有Hibernate查询,但它不工作... 文件的错误。由于关系,无法获取。

  • 问题内容: 我有dbo.Users表 然后我有dbo.Phones表 然后我有dbo.Relationship表 我如何进行查询返回 这就是我到目前为止所得到的。 问题答案: 在这里,将“关系”表视为“用户”和“电话”表之间的中间人。它与映射表是多对多关系。将您的用户加入到关系中,然后将其加入到您的电话中。 可以这样想: 用户: 您好关系,我的UserId = 1,我对那个UserId有什么电话I

  • 我刚开始学习spring boot,正在使用一个H2数据库,我已经得到了大部分的工作,但我遇到了麻烦,试图提出一个稍微复杂的请求。我有两个表'user'和'purche',我想创建和结束点,返回包含给定用户ID的所有购买。如果我使用SQL联接或一些类似的查询,这似乎很简单,但我不知道如何实现。 我有一个用于用户和购买的存储库(CrudRepository),然后有一个用于从数据库获取相关数据的服务

  • 问题内容: 我正在尝试创建一个用于在PHP上执行oracle sql语句的类。 这是我的index.php,我正在尝试调用我的函数 和我的dbcontrol.php用于我的功能 我不确定似乎有什么问题。但是每次我运行这个。页面上未显示任何内容。没有结果,没有数据。但是我确信数据库中有数据。 问题答案: 您总是得到空白页的原因是: oci_num_rows()函数不会返回您可能认为的所选行数。它返回

  • 问题内容: 我想在Cloud Firestore中定义这两个集合。一些示例数据如下所示: 播放清单: 名称:“ playlist1” songCount://要实时计算 歌曲: 标题:“ song1” playlistId:“ playlist1” 标题:“ song2” playlistId:“ playlist1” 标题:“ song3” playlistId:“ playlist1” 此外,