手动使用Hibernate序列生成器

时间:2009-09-09 15:21:06

标签: java hibernate jpa jdbc sequence

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

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

类似的问题here at SO,但我不是解决方案的粉丝,因为它需要另一个表来维护,看起来像是一个奇怪的关系。

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

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

感谢。

3 个答案:

答案 0 :(得分:1)

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

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

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

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

答案 1 :(得分: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;
    }

答案 2 :(得分:1)

我认为您的任务的复杂性取决于您是否需要按顺序显示数字:

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

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

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

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