繁体   English   中英

JPA / MySql具有递增的主要和次要ID的特权

[英]JPA/MySql An eniity with incremental primary and secondary id

我有资源,比如说一本书。 我希望这本书具有书号和版本号

在创建操作上,我想要增量ID

book id     version id   status
1             0          ACTIVE
2             0          ACTIVE
3             0          ACTIVE

更新时,我想拥有相同ID的新版本

book id     version id   status
    1             0          INACTIVE    //Changed to inactive
    1             1          ACTIVE      //new row with same id
    2             0          ACTIVE
    3             0          ACTIVE

我有两个桌子可以达到这个目的

生成ID的表

  CREATE TABLE `BookIdGenerator` (
`id`int(11) NOT NULL AUTO_INCREMENT ,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

书桌

 CREATE TABLE `Book` (
         `id` int(11) NOT NULL ,
         `version` int(11) NOT NULL,
         `title` varchar(255) NOT NULL,
         `isbn` varchar(255) NOT NULL,

     PRIMARY KEY (`id`,`version`),
     foreign key (`id`) references BookIdGenerator(`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

实体类是

class Book{
private long id;
private int version;
//other fields

要达到此目的,正确的表结构JPA注释是什么?

没有任何单独的表,我可以在id和version处使用@Id,但这不允许在持久存储时检索分配给对象的ID。

更新:我可以有一个Emeddable BookId类(具有书ID和版本),并且可以在Book中使用@EmbeddedId,但是我必须编写一个ID生成器来生成ID。 我该怎么办,这样在坚持使用create方法之前不必写一个生成器来分配id?

JPA @版本

版本列的预期用途与JPA中的预期用途不同。

版本字段用于支持单个数据库记录的乐观锁定。 每次事务尝试更新记录时,都会将版本字段与数据库中的值进行比较。 如果它们相同,则没有其他事务更新记录。 记录将被更新,版本列将被更改。 如果它们不相同,则其他事务更新记录,并且将引发OptimisticLockException。

在更新实体(使用JPA的merge())时,JPA更新现有记录。

在您的问题中,当您“更新”记录时,实际上是在创建(持久)新记录。

此外,版本字段由JPA管理,应用程序不应触摸-只读。 在您的示例中,您正在使用指定的版本号创建新记录。

主键

您已经为Book定义了PrimaryKey,但是,您需要多个记录来保存相同的PrimaryKey。 这将失败,因为PrimaryKey必须是唯一的。

在这种情况下,您的ID和版本构成一个复合主键,您需要将这些字段分离到一个单独的类中; 主键类

如果您确实想将每个更改记录为一条记录作为单独的记录,则需要特定于应用程序的版本控制,因为您不能出于目的使用JPA版本字段。

Book_id     Book_Update_id   status    JPA_Version
    1             0          INACTIVE       0
    1             1          ACTIVE         0
    2             0          ACTIVE         0
    3             0          ACTIVE         0 

我保留了“ JPA版本”列,但是如果您不修改记录,则不需要这样做。

因此您的书将看起来像这样。

@Entity //Tell JPA this is an entity to be mapped to your DB.
@IdClass(BookId.class) //you need to repeat the PK fields in this class
class Book{
@Id @Column(name=”Book_id”) //Both id and bookUpdateId annotated with @ID
private long id;            //Together they for a compound Primary Key
@Id @Column(name=”Book_Update_id”)
String bookUpdateId
@Version @Column(name=”JPA_Version”) //Tell JPA where to record its version info
private int version;

在创建新记录时,由应用程序决定是否要根据记录的现有值确定id和bookUpdateId值。 JPA无法知道这一点。 因此,不需要单独的表来支持ID生成。

有关所有这些主题,请参见Mike Keith和Merrick Schincariol撰写的Pro JPA 2,一个很好的介绍及其他内容。 这也将详细解释@IdClass。

暂无
暂无

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

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