【发布时间】:2019-04-12 18:59:43
【问题描述】:
如何在JPA 或Hibernate 5 中通过sequence name 获得sequence nextval?
我在Oracle DB 中对以下TEST_SEQ 和Postgresql DB 中的ANOTHER_NAME_SEQ 进行了排序。
我需要一个带有以下签名的方法
public Long getSequenceByName(String sequenceName){}
当我调用此方法时,它必须从现在使用的 DB 返回 nextval。
我有几个想法,但都不合适。
1) 将每个数据库的本地查询存储在属性中,并编写如下方法:
@Value("${query}")//"SELECT {name}.NEXTVAL FROM DUAL"
private StringQuery;
public Long getSequenceByName(String sequenceName){
uery q = em.createNativeQuery(StringQuery.replace("{name}", sequenceName));
return (java.math.BigDecimal) q.getSingleResult();
}
但我需要用占位符存储查询字符串并将占位符替换为序列名称,存储每个数据库的查询。
2) 创建只有一个字段@Id 的实体。插入实体和getId(序列值)。
但是如果在不同的数据库中是不同的序列名称 - ???
3) 使用this。但它适用于hibernate 3,我不知道这是否是一个好方法。
编辑:
我试试这个解决方案:
@Component
public class SequenseRepository {
@PersistenceContext
private EntityManager em;
@Transactional
public Long getID(final String sequenceName) {
final List<Long> ids = new ArrayList<>(1);
Session session = em.unwrap(Session.class);
session.doWork(connection -> {
DialectResolver dialectResolver = new StandardDialectResolver();
Dialect dialect = dialectResolver.resolveDialect((DialectResolutionInfo) connection.getMetaData());
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
preparedStatement = connection.prepareStatement( dialect.getSequenceNextValString(sequenceName));
resultSet = preparedStatement.executeQuery();
resultSet.next();
ids.add(resultSet.getLong(1));
}catch (SQLException e) {
throw e;
} finally {
if(preparedStatement != null) {
preparedStatement.close();
}
if(resultSet != null) {
resultSet.close();
}
}
});
return ids.get(0);
}
}
我得到了例外:
java.lang.ClassCastException: oracle.jdbc.driver.OracleDatabaseMetaData cannot be cast to org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo
【问题讨论】:
-
@aurelius 你能更仔细地阅读我的问题吗?具体来说,第3点,看看我给的链接
-
第 3 点还展示了一种用于休眠 4 的方法。使用方言是一种很好的方法。 (至少我们是这样做的,而且效果很好)。
-
但是我用的是hibernate5。感谢您分享有关使用此方法的信息。我还想学习其他方法。
标签: java hibernate jpa sequence