Данные Spring JPA + собственный запрос - заменить строку запроса в зависимости от профиля - PullRequest
0 голосов
/ 05 октября 2018

У меня есть служба:

@Service
public class MessageServiceImpl implements MessageService {

    private final MessageRepository smevMessageRepository;
    private final Environment environment;

    public MessageServiceImpl(MessageRepository messageRepository, Environment environment) {
        this.messageRepository= messageRepository;
        this.environment = environment;
    }

    @Override
    public List<Message> findReadyToSend() {
        if (environment.acceptsProfiles("postgre")) {
            return messageRepository.findReadyToSendPostgre();
        }
        return messageRepository.findReadyToSendOracle();
    } 

И это мой репозиторий:

@Repository
public interface MessageRepository extends JpaRepository<Message, String> {

    @Query(value = "select sm.* from MESSAGES sm ...", nativeQuery = true)
    List<Message> findReadyToSendOracle();

    @Query(value = "select sm.* from MESSAGES sm ...", nativeQuery = true)
    List<Message> findReadyToSendPostgre();

Если я запускаю весенний загрузочный сервер с oracle profile, я вызываю findReadyToSendOracle метод и, если postgre profile - findReadyToSendPostgre метод.Это работает.Но это решение плохо.Я думаю.Потому что я пишу жесткий код для проверки профиля.и мой репозиторий имеет 2 метода для разных БД.

Как правильно это реализовать?

1 Ответ

0 голосов
/ 07 октября 2018

С какими проблемами вы сталкиваетесь при адаптации к JPQL?Использование родных / пользовательских функций?Это может показаться слишком сложным, но вы можете найти способ, используя критерии + функция function из JPA 2.1+, взгляните на эту статью .

Onс другой стороны, я нашел здесь мой старый обходной путь, который мог бы помочь.Есть простой способ решить эту проблему, используя несколько ярлыков с аннотацией @Profile и некоторые дополнительные интерфейсы.

Если вы предоставляете интерфейс с ожидаемым собственным методом запроса, расширяющим JpaRepository, например:

@NoRepositoryBean
public interface MessageRepository extends JpaRepository<Message, String>{

    List<Message> findByReady();

}

Обратите внимание на @NoRepositoryBean, избегая дублирования bean-компонентов с профильной специализацией.

Затем просто предоставьте свои реализации в соответствии с вашими потребностями:

@Repository
@Profile("oracle")
public interface MessageOracleRepository extends MessageRepository {

    @Query(value = "select m.* from Message m where m.ready = false", nativeQuery = true)
    List<Message> findByReady();

}

... и ...

@Repository
@Profile("mysql")
public interface MessageMySQLRepository extends MessageRepository {

    @Query(value = "select m.* from Message m where m.ready = true", nativeQuery = true)
    List<Message> findByReady();

}

Теперь вам нужно будет только указать нужный профиль, внедрить и использовать правильные собственные запросы.

Как вы видите, я упростил запросы для простоты.Взгляните на этот репозиторий с адаптированным кодом.

...