在多线程中休眠@GeneratedValue序列

时间:2018-08-08 14:55:18

标签: java multithreading hibernate jpa spring-data-jpa

我有2个主要的实体Dog和Cat,除了iddataVersion之外,它们都有不同的字段,
hibernate或db都不会生成id字段。
dataVersion字段是使用@GeneratedValue以相同的db序列生成的。

问题是这样的,我有2个线程:

  1. 线程1创建实体Dog将其持久保存,然后休眠30秒
  2. 线程2在线程1之后10秒钟开始,线程2保留实体Cat并提交。
  3. 线程1在30秒后提交

我希望数据库具有的是具有数据版本2的实体Dog和具有数据版本1的实体Cat。  但是实体Dog具有dataVersion 1,而实体Cat具有dataVersion2。

我在互联网上搜索了@GeneratedValue的分配,而我found out则在刷新事务时生成了该值,因此我关闭了自动刷新。仅在事务提交后才进行刷新,但仍然没有得到预期的结果。

我想知道导致此问题的原因。


@Entity
@Getter
@Setter
public class Dog {
    @Id
    private String id;

    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "dataVersionGen")
    @SequenceGenerator(name = "dataVersionGen", sequenceName = "DATA_VER_SEQ")
    private Long dataVersion;
}

@Entity
@Getter
@Setter
public class Cat {
    @Id
    private String id;

    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "dataVersionGen")
    @SequenceGenerator(name = "dataVersionGen", sequenceName = "DATA_VER_SEQ")
    private Long dataVersion;
}

这是开始运行时要评估的代码

@Component
public class Example {
    private ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
    @Autowired
    private DBAccessor accessor;

    @PostConstruct
    public void example() {
        threadPoolTaskExecutor.initialize();

        // Starts dog's thread
        threadPoolTaskExecutor.execute(() -> {
            Dog dog = new Dog();
            dog.setId(UUID.randomUUID().toString());

            accessor.persist(dog);

            sleep(30 * SECOND);

            accessor.commit();
        });

       // Starts dog's thread
        threadPoolTaskExecutor.execute(() -> {
            sleep(10 * SECOND);

            Cat cat = new Cat();
            cat.setId(UUID.randomUUID().toString());

            accessor.persist(cat);
            accessor.commit();
        });
    }
}

1 个答案:

答案 0 :(得分:0)

持久性提供程序可以随时随地自由生成ID,只要它遵守规范(即只要实体最终在数据库中具有唯一ID)即可。

您不应该假定ID是在刷新时生成的,因为不一定是这种情况。

而且您不必在乎猫的ID是比狗的ID低还是高:重要的是ID是唯一的。