Репозитории Spring Data Jpa с использованием фрагментов, как применять подсказки запросов и граф сущностей - PullRequest
3 голосов
/ 21 мая 2019

Начиная с Spring 5, у нас есть возможность обогатить наш репозиторий JPA несколькими репозиториями фрагментов.

Механизм довольно прост: объявите и реализуйте интерфейс.

public interface CustomRepository<T,K> {
    // my very special finder
    T findByIdCustom(K id);
}
public class CustomRepositoryImpl implements CustomRepository<T,K> {
    T findByIdCustom(K id) {
       // retrieve the item
    }
}

Затем используйте это так:

public interface ItemRepository 
  extends JpaRepository<Item, Long>, CustomRepository<Item, Long> {
}

Теперь предположим, что я хочу установить некоторые подсказки запроса и / или граф сущностей, например:

public interface ItemRepository extends JpaRepository<Item, Long>, CustomRepository<Item, Long>{
    @QueryHints(value = { @QueryHint(name = "name", value = "value")},
              forCounting = false)
    @EntityGraph(value = "Item.characteristics") 
    Item findByIdCustom(Long id);
}

Поскольку у меня есть пользовательская реализация, приведенные выше подсказки к запросу и граф сущностей, которые хорошо работают с JpaRepository методами, здесь игнорируются.

Мой вопрос:

Как применить метаданные метода к базовому запросу?

1 Ответ

1 голос
/ 03 июня 2019

То, что вы спрашиваете, нельзя заставить работать с использованием аннотаций, потому что они предназначены для использования с методами репозитория, для которых Spring предоставляет реализацию. Он обязательно игнорируется Spring для пользовательских методов - поскольку ваш пользовательский код отвечает за построение, настройку и выполнение запроса, Spring не может волшебным образом вмешиваться в промежуточный процесс и вводить подсказки запроса. По сути, если вы хотите два разных набора подсказок для пользовательского метода запроса, вам понадобятся две разные реализации.

Однако вы можете попробовать шаблон типа метода шаблона, подобный следующему:

public interface CustomRepository<T,K> {

    T findByIdCustom(K id);
    Map<String, Object> getHintsForFindByIdCustom();
    // you'll probably need a default implementation for getHintsForFindByIdCustom here, unless it's possible to make CustomRepositoryImpl  abstract - not sure how Spring Data will behave in this case
}

public class CustomRepositoryImpl<T, K> implements CustomRepository<T,K> {
    T findByIdCustom(K id) {
       TypedQuery<T> query= em.createQuery("...");
       getHintsForFindByIdCustom().forEach((key, value) -> query.setHint(key, value));
       return query.getResultList().iterator().next();
    }
}

public interface ItemRepository extends JpaRepository<Item, Long>, CustomRepository<Item, Long>{
    default Map<String, Object> getHintsForFindByIdCustom() {
        return Map.of("name", "value");
    }
}

public interface UserRepository extends JpaRepository<User, Long>, CustomRepository<User, Long>{
    default Map<String, Object> getHintsForFindByIdCustom() {
        return Map.of("name", "some-other-value");
    }
}

Обратите внимание, что я не пробовал вышеуказанный код. Если это не работает, то, возможно, вы могли бы попробовать отдельную реализацию для CustomRepositoryImpl для каждого класса сущностей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...