ip6*_*696 4 java hibernate jpa sequence
我怎样才能获得sequence nextval的JPA或Hibernate 5通过sequence name?
我有序列以下TEST_SEQ的OracleDB和ANOTHER_NAME_SEQ在PostgresqlDB。
我需要一个具有以下签名的方法
public Long getSequenceByName(String sequenceName){}
Run Code Online (Sandbox Code Playgroud)
当我调用这个方法时,它必须nextval从现在使用的 DB返回。
我有几个想法,但都不合适。
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();
}
Run Code Online (Sandbox Code Playgroud)
但是我需要用占位符存储查询字符串并将占位符替换为序列名称,存储每个数据库的查询。
2) 创建只有一个字段的实体@Id。插入实体和 getId(序列值)。
但是如果在不同的数据库中是不同的序列名称 - ???
3)使用这个。但它用于 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);
}
}
Run Code Online (Sandbox Code Playgroud)
我得到了豁免:
java.lang.ClassCastException: oracle.jdbc.driver.OracleDatabaseMetaData cannot be cast to org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo
Run Code Online (Sandbox Code Playgroud)
由于这篇文章,我找到了解决方案在此处输入链接描述
public interface SequenceRepository {
int getNext(String sequenceName);
}
Run Code Online (Sandbox Code Playgroud)
和每个数据库的实现:
@Profile("oracle")
@Component("oracleSequenceRepository")
public class OracleSequenceRepository implements SequenceRepository{
private final DataSource dataSource;
@Autowired
public OracleSequenceRepository(@Qualifier("dataSource") DataSource dataSource) {
this.dataSource = dataSource;
}
@Transactional(readOnly = true)
@Override
public int getNext(String sequenceName) {
AbstractSequenceMaxValueIncrementer incr = new OracleSequenceMaxValueIncrementer(this.dataSource, sequenceName);
return incr.nextIntValue();
}
}
Run Code Online (Sandbox Code Playgroud)
和
@Profile("postgre")
@Component("postgresSequenceRepository")
public class PostgreSequenceRepository implements SequenceRepository{
private final DataSource dataSource;
@Autowired
public PostgreSequenceRepository(@Qualifier("dataSource") DataSource dataSource) {
this.dataSource = dataSource;
}
@Transactional(readOnly = true)
@Override
public int getNext(String sequenceName) {
AbstractSequenceMaxValueIncrementer incr = new PostgresSequenceMaxValueIncrementer(this.dataSource, sequenceName);
return incr.nextIntValue();
}
}
Run Code Online (Sandbox Code Playgroud)