简体   繁体   English

如何通过JPA保留数据而无需主键

[英]How to persist data through JPA without needing a primary key

I have data that flows through my application and normally it doesn't need to be bothered but to implement a new feature I need to store it temporarily (eg 1 hr). 我有流经我的应用程序的数据,通常不需要打扰,但是要实现一项新功能,我需要将其临时存储(例如1个小时)。 The data going in can be the exact same as something that is already in there so there is no need for a primary key. 输入的数据可以与其中已经存在的数据完全相同,因此不需要主键。 However, with JPA Entities need an Id but I don't need/want one. 但是,使用JPA实体需要一个ID,但我不需要/想要一个。 This is preventing me from getting it working. 这使我无法正常工作。

This is through Spring using JPA. 这是通过Spring使用JPA实现的。 Since the data is moving in and out of the database frequently, the use of an auto generated ID is discouraged because it'll go through the IDs in a few years time. 由于数据经常移入和移出数据库,因此不建议使用自动生成的ID,因为它会在几年后通过ID。 I have tried to make it embeddable to which it says I need to do a component scan to find where it is used but if I make it an entity then it gives me the error that it needs a primary key. 我试图使其可嵌入,它说我需要进行组件扫描以找到它的使用位置,但是如果我将其设置为实体,则它会提示我它需要主键。

This is my entity that stores the data I need to persist. 这是我的实体,用于存储我需要保留的数据。

@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

}

This is my repository to access the data. 这是我访问数据的存储库。

@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);
}

I can't figure out to get this to work. 我不知道该怎么做。 Again a primary key isn't needed since it's suppose to support duplicate entries. 同样,不需要主键,因为它假定支持重复项。 If there is another way around this without using JPA then I'm all for it but currently it seems to be the easiest to persist the data. 如果没有使用JPA的另一种解决方法,那么我全力以赴,但是目前看来,持久保存数据是最容易的。 If you need anymore information just let me know. 如果您需要更多信息,请告诉我。 I also might be missing something that can be done to avoid this all together but I'm not that familiar with JPA. 我也可能缺少可以避免这些事情的方法,但是我对JPA并不熟悉。 So all help is appreciated. 因此,感谢所有帮助。

You shouldn't run out of IDs for a column if you use the correct size. 如果使用正确的大小,则不应使ID用完一列。 Stop trying to fight your framework and just add an auto-incrementing column. 停止尝试与您的框架作斗争,只添加一个自动递增的列。

https://hashrocket.com/blog/posts/running-out-of-ids 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. 假设业务非常好,我们每分钟将10,000条记录插入表中。 So, how long would it take to max out our sequence? 那么,最大化序列所需的时间是多少? 1750380517 years 1750380517年

From How large can an id get in postgresql ID可以进入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

If you're desperate to not use an id column for some reason I cannot possibly comprehend, it looks like you can do it in JPA by making every column part of the primary key description, but then your deletes and updates will delete/update any number of records. 如果由于某种我无法理解的原因而急于不使用id列,则看起来您可以在JPA中通过将每个列作为主键描述的一部分来进行操作,但是您的删除和更新操作将删除/更新任何记录数。 I HAVE NOT TRIED THIS. 我没有尝试过。 I WOULD NOT IMPLEMENT THIS ON A PRODUCTION SERVER. 我不会在生产服务器上实现此功能。

https://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#No_Primary_Key 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. 在这种情况下,最好的解决方案通常是将生成的ID添加到对象和表。 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. 您可以将此唯一的列集用作JPA中的ID。 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. JPA Id不必总是与数据库表的主键约束匹配,也不需要主键或唯一约束。

If your table truly has no unique columns, then use all of the columns as the id. 如果您的表确实没有唯一列,则将所有列用作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. 通常,发生这种情况时,数据是只读的,因此,即使表允许具有相同值的重复行,对象也将始终相同,因此JPA认为它们是同一对象无关紧要。 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. 如果您的对象没有ID,但是其表具有ID,则可以。 Make the object an Embeddable object, embeddable objects do not have ids. 将对象设为可嵌入对象,可嵌入对象没有ID。 You will need a Entity that contains this Embeddable to persist and query it. 您将需要一个包含此Embeddable的实体来持久化并查询它。

Jazzepi stated was correct but I was strictly requested not to use an auto generated number as the ID. Jazzepi说的是正确的,但严格要求我不要使用自动生成的数字作为ID。 Therefore, people linked this here depicting using a UUID. 因此,人们在此处使用UUID对此进行了链接。 This is the best choice for this problem since the objects in the database are timed to be in there no more than a few hours. 这是解决此问题的最佳选择,因为数据库中的对象被安排在其中的时间不超过几个小时。 Since this is the case, a UUID will never overflow and the likelihood of a repeated UUID inside of the table any given time is almost zero since most won't stay there. 既然是这种情况,那么UUID将永远不会溢出,并且在任何给定时间在表内重复UUID的可能性几乎为零,因为大多数情况下不会保留在那里。

New Entity class: 新实体类:

@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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM