JPA / Hibernate5 получить последовательность далее по имени последовательности - PullRequest
0 голосов
/ 09 ноября 2018

Как я могу получить sequence nextval в JPA или Hibernate 5 на sequence name?

У меня есть последовательность, следующая TEST_SEQ в Oracle DB и ANOTHER_NAME_SEQ в Postgresql DB.

Мне нужен метод со следующей подписью

public Long getSequenceByName(String sequenceName){}

И когда я вызываю этот метод, он должен вернуть 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, и я не знаю, хороший ли это подход.

EDIT:

Я пробую это решение:

@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;

1 Ответ

0 голосов
/ 09 ноября 2018

Я нашел решение благодаря этой статье введите описание ссылки здесь

    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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...