基本上,我想要一种以与数据库无关的方式访问序列值的方法。用例是我在实体上有一个字段,我想根据递增值(ID 除外)来设置该字段。

例如,假设我有一个 Shipment 实体。在创建货件后的某个时刻,它就会被发货。一旦发货,就会为其生成并分配清单编号。清单号码看起来像 M000009 (“M”之后的内容是序列中的左填充值)。

有人问过类似的问题 在SO这里 ,但我不喜欢该解决方案,因为它需要另一个表来维护,并且看起来像是一种奇怪的关系。

有谁知道是否可以使用像 hibernate 这样的东西 MultipleHiLoPerTableGenerator 作为 ID 生成器以外的东西?

如果这是不可能的,有谁知道有什么库可以处理这个问题(使用 hibernate 甚至只是纯 JDBC)。我不想自己编写这个(并且必须处理预取值、锁定和同步)。

谢谢。

有帮助吗?

解决方案

我认为您的任务的复杂性取决于您的清单编号是否需要连续:

  • 如果您不需要连续的清单编号,那么很高兴,可以使用序列。
  • 如果您确实需要顺序清单编号(或者您的数据库不支持序列),则使用具有适当锁定的 id 表,以便每个事务获得唯一的顺序值。

那么我能想到的有两个选择:

  • 在客户端上编写必要的 JDBC 代码,确保(如果清单编号是连续的)正在使用的事务与数据库更新的事务相同。
  • 当发生适当的更新时,使用触发器创建清单编号。

我认为我的偏好是触发器,因为事务方面的事情将得到处理,尽管这意味着对象需要在客户端上刷新。

其他提示

我没有阅读链接的类似解决方案,但听起来像是我做的事情。我为序列创建了一个表。我在表中为我需要的每个序列类型添加了一行。

然后我有一个序列生成器类,它将执行必要的sql查询以获取和更新特定命名序列的序列值。

我使用hibernate的Dialect类以db中立方式执行它。

我也会'缓存'序列。我会将存储的序列值碰到一个大数字,然后从我的生成器类中分配那些分配的序列。如果类被销毁(即app关闭),序列生成器的新实例将以存储的值启动。 (我的序列号有差距并不重要)

这是一个代码示例。我想提醒一下 - 我没有提到这个,它需要弹簧代码。说完这个之后,它仍然应该提供你想要做的事情。

public Long getManifestNumber() {
        final Object result = getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session sess) throws HibernateException, SQLException { 
                SQLQuery sqlQuery = sess.createSQLQuery("select MY_SEQUENCE.NEXTVAL from dual");
                sqlQuery.uniqueResult();
            }
        });
        Long toReturn;
        if (result instanceof BigDecimal) {
            toReturn = ((BigDecimal)result).longValue();
        }
        return toReturn;
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top