每次调用方法时,我都想从我的域对象(表)ID中获得唯一的ID。这样就不会重复ID。我有一个返回唯一ID的函数。

public static Long generateID (Short company)
        throws Exception
{
    IDDAO iDDAO = SpringApplicationContext.getBean (IDDAO.class);
    ID iD = iDDAO.findByNaturalKey (new IDNatKey (company);

    if (iD != null)
    {
        // Check if ID has reached limit, then reset the ID to the first ID
        if (iD.getLatestIDno ().longValue () == iD.getLastIDno ().longValue ())
        {
            iD.setLatestIDno (iD.getFrstIDno ());
        }

        // Get next ID
        iD.setLatestIDno (iD.getLatestIDno () + 1);
        // update database with latest id
        iDDAO.update (iD);

        return iD.getLatestIDno ();
    }
}

问题是,如果从两台计算机访问应用程序并从UI按下按钮以完全同时生成ID,则有时此方法返回的ID重复

例如
Long ID = TestClass.generateID (123);

这有时会给我重复。

我做了这样的方法
public static synchronized Long generateID (Short company)
        throws Exception

因此一次只能有一个线程可以使用此功能,但是仍然存在重复的问题。

我不希望使用数据库序列,因为如果事务回滚,我不希望ID序列中存在间隙,在这种情况下,序列仍将递增,这是我不希望的。中间的间隙可以但不能结束。例如,我们有1、2和3作为ID,然后有2个回滚,这是可以的。但是如果3回滚,我们应该在另一个用户到来时再次获得3,如果有序列,它将给出4

请帮我告诉我我做错了什么吗?静态同步还会导致其他线程同时进入该函数吗?我在该类中还有许多其他静态(但不同步)功能。如果我将其静态同步,这也会对他们造成问题吗?

谢谢

艾登

最佳答案

保留2个唯一ID:

  • 由数据库提供的内部事务ID,每次创建新事务时由自动增量创建。如果回滚事务,则可能会出现空白。
  • 一个漂亮的,无间隙的“票证ID”,仅在事务成功提交后才分配。

  • 从数据库中分配两者-最好将所有共享状态都保留在那里,因为数据库将保证ACID,而Java并发性则很棘手。

    10-06 14:44