Java 如何在不需要主键的情况下通过JPA持久化数据
我有通过我的应用程序的数据,通常它不需要麻烦,但要实现一个新功能,我需要临时存储它(例如1小时)。输入的数据可以与已经存在的数据完全相同,因此不需要主键。然而,JPA实体需要一个Id,但我不需要/想要一个。这使我无法让它工作 这是通过Spring使用JPA实现的。由于数据经常进出数据库,因此不鼓励使用自动生成的ID,因为它将在几年内通过ID。我曾尝试将其嵌入其中,它说我需要进行组件扫描以找到使用它的位置,但如果我将其作为一个实体,它会给我一个错误,即它需要一个主键 这是存储需要持久化的数据的实体Java 如何在不需要主键的情况下通过JPA持久化数据,java,spring,hibernate,jpa,spring-data-jpa,Java,Spring,Hibernate,Jpa,Spring Data 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);
}
@存储库
公共接口QuoteOrderHistoryRepository扩展了JpaRepository{
@查询(“从QuoteOrderHistoryQ中删除,其中q.orderHistoryDate>date”)
void deleteAllExpired(日期);
@查询(“从QuoteOrderHistory q中选择q,其中q.storeNumber=?1和q.invoiceNumber=?2 ORDER BY q.orderHistoryDate DESC”)
列出FindAllByStore和InvoiceDesc(int storeNumber,字符串invoiceNumber);
}
我不知道该怎么做。同样,主键是不需要的,因为它应该支持重复的条目。如果有另一种方法不使用JPA,那么我完全赞成,但目前看来它是最容易持久化数据的方法。如果你需要更多的信息,请告诉我。我也可能遗漏了一些可以避免这一切的方法,但我对JPA不是很熟悉。因此,非常感谢您提供的所有帮助。如果您使用了正确的大小,就不应该用完列的ID。停止与框架抗争,只需添加一个自动递增列 假设业务非常好,我们每年插入10000条记录 一分钟后到我们桌上。那么,我们需要多长时间才能完成我们的任务 序列1750380517年 从 如果由于某种我无法理解的原因,您不顾一切地不使用id列,那么您可以在JPA中通过使每一列成为主键描述的一部分来实现,但是您的删除和更新将删除/更新任意数量的记录。我没有试过这个。我不会在生产服务器上实现这一点 有时对象或表没有主键。最佳解决方案 在这种情况下,通常是将生成的id添加到对象和 桌子如果没有此选项,有时会出现列或 表中组成唯一值的列的集合。你可以用 这组独特的列作为您在JPA中的id。JPA Id不存在 始终必须匹配数据库表主键约束,也不是 需要主键或唯一约束 如果表中确实没有唯一的列,则使用所有列 作为id。通常在发生这种情况时,数据是只读的,因此 如果表允许具有相同值的重复行,则对象 无论如何都是一样的,所以JPA认为他们 是同一个物体。允许更新和删除的问题是 无法唯一标识对象的行,因此 将更新或删除匹配的行 如果您的对象没有id,但它的表有id,则可以。 使对象成为可嵌入对象,可嵌入对象没有 身份证。您需要一个包含此可嵌入文件的实体才能持久化 并质疑它
Jazzepi说的是正确的,但我被严格要求不要使用自动生成的数字作为ID。因此,人们使用UUID链接了这一描述。这是解决此问题的最佳选择,因为数据库中的对象被计时在那里不超过几个小时。在这种情况下,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
}
如果您使用的是Hibernate5,那么可以使用UUIDGenerator。请看,基于时间的UUID甚至不太可能导致问题。@chrylis基于时间的UUID如何帮助这种情况?它们生成速度更快(不需要随机性),但如果使用接口地址,仍然保证是唯一的。@chrylis比什么快?随机(类型4)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
}