有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在不需要主键的情况下通过JPA持久化数据

我的应用程序中有数据,通常不需要麻烦,但要实现一个新功能,我需要临时存储它(例如1小时)。输入的数据可以与已经存在的数据完全相同,因此不需要主键。然而,JPA实体需要一个Id,但我不需要/想要一个。这让我无法工作

这是通过Spring使用JPA实现的。由于数据经常进出数据库,因此不鼓励使用自动生成的ID,因为它会在几年后通过ID。我曾尝试将其嵌入其中,它说我需要进行组件扫描,以找到它的使用位置,但如果我将其作为实体,它会给我一个错误,即它需要主键

这是我的实体,它存储我需要保存的数据

@Entity
@Table(name = "quoteOrderHistory")
public class QuoteOrderHistory {

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

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

    @Column(name = "quoteSaleDate")
    private Date quoteSaleDate;

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

    @Column(name="orderHistoryDate")
    private Timestamp orderHistoryDate;

    // Constructors, Getters and Setters

}

这是我访问数据的存储库

@Repository
public interface QuoteOrderHistoryRepository extends JpaRepository<QuoteOrderHistory, Long> {

    @Query("DELETE FROM QuoteOrderHistory q WHERE q.orderHistoryDate > date")
    void deleteAllExpired(Date date);

    @Query("SELECT q FROM QuoteOrderHistory q WHERE q.storeNumber = ?1 AND q.invoiceNumber = ?2 ORDER BY q.orderHistoryDate DESC")
    List<QuoteOrderHistory> findAllByStoreAndInvoiceDesc(int storeNumber, String invoiceNumber);
}

我不知道该怎么做。同样,主键也不需要,因为它应该支持重复的条目。如果有其他方法不使用JPA,那么我完全赞成,但目前看来,它似乎是最容易保存数据的方法。如果你需要更多信息,请告诉我。我也可能错过了一些可以避免这一切的方法,但我对JPA不太熟悉。因此,我们非常感谢您的帮助


共 (2) 个答案

  1. # 1 楼答案

    如果使用了正确的大小,就不应该用完列的ID。不要再试图对抗你的框架了,只需添加一个自动递增的列即可

    https://hashrocket.com/blog/posts/running-out-of-ids

    Let's say business is so good that we are inserting 10,000 records per minute into our table. So, how long would it take to max out our sequence? 1750380517 years

    How large can an id get in postgresql

    Name        Storage Size    Description                       Range
    smallint    2 bytes         small-range integer               -32768 to +32767
    integer     4 bytes         usual choice for integer          -2147483648 to +2147483647
    bigint      8 bytes         large-range integer               -9223372036854775808 to 9223372036854775807
    serial      4 bytes         autoincrementing integer          1 to 2147483647
    bigserial   8 bytes         large autoincrementing integer    1 to 9223372036854775807
    

    如果你因为某种我无法理解的原因而不顾一切地不使用id列,那么你可以在JPA中通过使每一列成为主键描述的一部分来做到这一点,但是你的删除和更新将删除/更新任意数量的记录。我没有试过这个。我不会在生产服务器上实现这一点

    https://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#No_Primary_Key

    Sometimes your object or table has no primary key. The best solution in this case is normally to add a generated id to the object and table. If you do not have this option, sometimes there is a column or set of columns in the table that make up a unique value. You can use this unique set of columns as your id in JPA. The JPA Id does not always have to match the database table primary key constraint, nor is a primary key or a unique constraint required.

    If your table truly has no unique columns, then use all of the columns as the id. Typically when this occurs the data is read-only, so even if the table allows duplicate rows with the same values, the objects will be the same anyway, so it does not matter that JPA thinks they are the same object. The issue with allowing updates and deletes is that there is no way to uniquely identify the object's row, so all of the matching rows will be updated or deleted.

    If your object does not have an id, but its table does, this is fine. Make the object an Embeddable object, embeddable objects do not have ids. You will need a Entity that contains this Embeddable to persist and query it.

  2. # 2 楼答案

    Jazzepi说的是正确的,但我被严格要求不要使用自动生成的数字作为ID。因此,人们用UUID链接了这个here描述。这是解决这个问题的最佳选择,因为数据库中的对象被计时在那里不超过几个小时。既然是这种情况,UUID永远不会溢出,而且在任何给定时间表中重复UUID的可能性几乎为零,因为大多数UUID不会留在表中

    新实体类:

    @Entity
    @Table(name = "quoteOrderHistory")
    public class QuoteOrderHistory {
    
        @Id
        @GeneratedValue(generator = "uuid")
        @GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
        @Column(name = "uuid", unique = true)
        private String uuid;
    
        @Column(name = "storeNumber")
        private int storeNumber;
    
        @Column(name = "invoiceNumber")
        private String invoiceNumber;
    
        @Column(name = "quoteSaleDate")
        private Date quoteSaleDate;
    
        @Column(name="orderTotal")
        private BigDecimal orderTotal;
    
        @Column(name="orderHistoryDate")
        private Timestamp orderHistoryDate;
    
        // Constructor, getters, setters
    
    }