【问题标题】:JPA/Hibernate5 get sequence nextval by sequence nameJPA/Hibernate5 通过序列名称获取序列 nextval
【发布时间】:2019-04-12 18:59:43
【问题描述】:

如何在JPAHibernate 5 中通过sequence name 获得sequence nextval

我在Oracle DB 中对以下TEST_SEQPostgresql 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&#xd;

【问题讨论】:

  • @aurelius 你能更仔细地阅读我的问题吗?具体来说,第3点,看看我给的链接
  • 第 3 点还展示了一种用于休眠 4 的方法。使用方言是一种很好的方法。 (至少我们是这样做的,而且效果很好)。
  • 但是我用的是hibernate5。感谢您分享有关使用此方法的信息。我还想学习其他方法。

标签: java hibernate jpa sequence


【解决方案1】:

感谢这篇文章enter link description here

,我找到了解决方案
    public interface SequenceRepository {
    int getNext(String sequenceName);
   }

每个数据库的实现:

@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();
    }
}

@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();
    }
}

【讨论】:

    【解决方案2】:

    试试这个:

    // Get metadata from connection
    DatabaseMetaData metaData = connection.getMetaData();
    
    // Create adapter between MetaData and DialectResolutionInfo
    DialectResolutionInfo info = new DatabaseMetaDataDialectResolutionInfoAdapter(metaData);
    
    // Resolve dialect
    DialectResolver dialectResolver = new StandardDialectResolver();
    Dialect dialect = dialectResolver.resolveDialect(info);
    
    // Use it
    System.out.println(dialect.getSelectSequenceNextValString(sequenceName));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-27
      • 1970-01-01
      • 2017-10-27
      • 2011-07-30
      • 2017-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多