4

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

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

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

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

如果那不可能,有谁知道处理这个的任何库(使用休眠甚至只是纯 JDBC)。我不想自己写这个(并且必须处理预取值、锁定和同步)。

谢谢。

4

3 回答 3

1

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

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

我使用 hibernate 的方言类以数据库中立的方式进行操作。

我也会“缓存”这些序列。我会将存储的序列值增加一个很大的数字,然后从我的生成器类中分配出那些分配的序列。如果类被销毁(即应用程序关闭),序列生成器的新实例将以存储的值启动。(在我的序列号中有一个空白并不重要)

于 2009-09-09T17:12:08.847 回答
1

这是一个代码示例。我想警告这一点 - 我没有编译这个,它需要弹簧代码。话虽如此,它仍然应该提供您想要做的事情的基础。

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;
    }
于 2009-09-09T17:15:33.530 回答
1

我认为您的任务的复杂性取决于您的清单编号是否需要按顺序排列:

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

然后你有两个我能想到的选择:

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

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

于 2009-09-09T17:42:47.937 回答