【问题标题】:Guarantee unique number generation with spring data and hibernate使用 spring 数据和休眠保证唯一的数字生成
【发布时间】:2013-03-21 08:14:21
【问题描述】:

我正在开发一个带有 spring 数据和休眠的 spring mvc webapp。

我有一个由布尔字段和整数字段组成的实体。

一开始,布尔字段为假,整数字段为空。

当布尔字段变为真时,我需要为整数字段分配一个等于 MAX(seq) +1 的唯一值

为此,我这样写我的服务方法:

@Override
public synchronized Obj save(Obj entry) {
    if (entry.getBool() && entry.getSeq() == null){
        Integer seq = objRepository.getLastSeq();
        if (seq == null){
            seq = 1;
        }
        entry.setSeq(seq);
    }
    return entry.save(entry);
}

在我的存储库中:

@Query("select MAX(seq)+1 FROM Obj")
Integer getLastSeq();

我将同步关键字放在服务方法中,以确保一次只有一个线程可以获得唯一的 MAX+1 数字。但我不确定它是否适用于所有情况以及是否正确方式。

我能确定它保证seq的唯一性吗?

谢谢 马可

【问题讨论】:

  • 只有英国到seq 专栏才能保证您的唯一性。
  • 我无法将其设置为 UK,因为某些实体必须具有整数值 null。只有当布尔值变为真时,整数才变为非空!
  • 好的,用户可以直接调用obj.setSeq()吗?
  • No.. 它以隐藏的输入类型传入和传出视图。
  • 在方法上同步基本上是在“this”上同步,在你的例子中是服务类。尽管我通常不喜欢这样做,但您实际上是在说只有一个线程将为您的服务类的每个实例执行该方法。如果保证您只存在一个服务类副本,那么我相信您没问题。但是,如果您有多个应用程序服务器,每个都有自己的副本,或者您正在创建对服务对象的多个引用,那么您不是。

标签: spring hibernate jpa spring-mvc spring-data


【解决方案1】:

您的 Integer 似乎是条目 ID,不是吗?那么为什么不使用数据库序列,例如带有@id 注释:

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;

【讨论】:

  • 不.. 它不是实体 ID。是一个整数,仅赋予布尔属性为真的实体。为了更加真实,这个实体代表一个考试。我只有在我成功通过考试时才会给出一个序列号!谢谢你的回答
  • 所以请检查此解决方法以回答 this 问题。
  • Meybe 更好的解决方案是向您的服务添加 initialazingbean 接口并检查表中的最大序列号,然后在您的保存方法中使用 AtomicInteger。每次你想要下一个整数时,你查询数据库女巫都不是最佳解决方案。
  • 这是我在发布此问题后想到的解决方案之一!但在我尝试找到不那么复杂的东西之前。
  • 你能告诉我在哪里可以找到关于你的评论的例子吗?
【解决方案2】:

示例如何为此目的使用初始化 bean。

@Service
public class SequenceInitializer implements InitializingBean{

    @Autowired
    private ObjRepository objRepository;

    @Autowired
    private Service service;

    @Override
    public void afterPropertiesSet() throws Exception {

        try {
           Integer max = objRepository.getLastSeq();
           service.setLastSeq(max);
        } catch(Exception e){...}

 }

在您的服务中 setLastSeq 将设置 AtomicInteger 字段。

【讨论】:

  • 我不明白这种方法是否对我有用。如果在第一次尝试中创建实体并将其保存为布尔值 false(因此整数为空),它是否可以工作。然后我更新实体设置 boolean true (so integer = maxValue +1)?
  • 所以让我们说清楚。如果某些条件为真,您希望有一个在保存时具有下一个整数值的字段。在您的解决方案中,每次保存实体时,您都会对数据库进行额外的查询(这不是一个好主意)。在上面的解决方案中,您只在应用程序启动时进行一次查询,并将最大值写入服务中的 AtomicInteger 字段。现在,当您下次调用 save 方法时,您可以从 atiomicInteger..getAndIncrement() 获取下一个整数值。该解决方案要快得多,并且同步块已经过时了。
猜你喜欢
  • 1970-01-01
  • 2012-08-02
  • 1970-01-01
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多