it-swarm.com.ru

Spring Boot, расширяющий CrudRepository

Я использую Hibernate в приложении Spring Boot. Я создаю новый CrudRepository для всех моих объектов Model, чтобы выполнять основные задачи CRUD. Они выглядят так:

@Repository
public interface FoobarCrudRepo extends CrudRepository<Foobar, Long> {
}

Но тогда мне всегда нужно делать некоторые дополнительные вещи, такие как пользовательские поисковые запросы с неравенствами и тому подобное. Я следую за образцом как это:

@Repository
public class FoobarDao {

    @PersistenceContext
    EntityManager em;

    public List<Foobar> findFoobarsByDate(Date date) {
        String sql = "select fb from Foobar fb where createdDate > :date";
        ...
        return query.getResultList();
    }
}

У меня вопрос, могу ли я объединить эти два понятия в один класс? Я попытался сделать его абстрактным классом, вот так:

@Repository
public abstract class FoobarCrudRepo extends CrudRepository<Foobar, Long> {

    @PersistenceContext
    EntityManager em;

    public List<Foobar> findFoobarsByDate(Date date) {
        String sql = "select fb from Foobar fb where createdDate > :date";
        ...
        return query.getResultList();
    }

}

Но тогда Spring не создал боб для этого.

Как я могу сделать это?

Спасибо!

6
James Watkins

Есть много способов, которыми вы могли бы достичь этого. Если вам действительно нужен абсолютный контроль, попробуйте это

interface FoobarRepositoryCustom{
    List<Foobar> findFoobarsByDate(Date date);
}

interface FoobarRepository extends CrudRepository<Foobar, Long>, FoobarRepositoryCustom

public class FoobarRespoitoryImpl implements FoobarRepositoryCustom{
    @PersistenceContext private EntityManager em;


    public List<Foobar> findFoobarsByDate(Date date) {
    String sql = "select fb from Foobar fb where createdDate > :date";
    ...
    return query.getResultList();
    }
}

Существует также возможность пойти по более простому маршруту, и запрос может быть автоматически сгенерирован для вас на основе имени метода. В вашем примере вы можете просто добавить это в свой FoobarCrudRepo, а Spring должен сделать все остальное, предполагая, что Foobar имеет свойство с именем CreatedDate

List<Foobar> findByCreatedDateGreaterThan(Date date);

Справочную информацию о том, как Spring может генерировать запросы на основе имени метода, см. В этом http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query- создание

13
jst

Абсолютно новичок в Spring Data, но после небольшого поиска у меня сложилось впечатление, что вам не нужно выходить из интерфейса, чтобы создать собственную логику. Вместо этого вы должны создать либо аннотированный метод интерфейса, либо метод интерфейса, который следует специальной схеме именования, либо метод интерфейса по умолчанию с пользовательской логикой: 

 enter image description here Скриншот из Baeldung: Введение в весну .

Здесь это ссылка на документацию. Уведомление " таблица 4. Поддерживаемые ключевые слова внутри имен методов ", которые можно использовать для создания методов интерфейса, чье имя передает информацию генератору кода о том, какой запрос создать (см. Часть таблицы ниже).

 enter image description here

1
Hervian

Проблема здесь в ключевом слове abstract.

@Repository
public abstract class FoobarCrudRepo extends CrudRepository<Foobar, Long>

Spring не создаст bean-компонент для класса, если он не является конкретным классом .. Вот почему вы получаете bean-компонент для него.

0
pmverma

Это то, что сработало для меня ...

@SpringBootApplication(scanBasePackages = { "com.myproject" })
@EnableJpaRepositories(basePackages="com.myproject.sprinbootapp.repository")
    @EntityScan("com.myproject.sprinbootapp.model")
    public class SpringbootAppWithDatabaseApplication {

        public static void main(String[] args) {
            SpringApplication.run(SpringbootAppWithDatabaseApplication.class, args);
        }
    }

@Service
public class TopicService {

    @Autowired
    private TopicRepository topicRepository;

    private List<Topics> topics = new ArrayList<Topics>();

    public List<Topics> getAllTopics(){
        List<Topics> listOfTopics = new ArrayList<Topics>();
        topicRepository.findAll().forEach(listOfTopics::add);;
        return listOfTopics;
    }

}

@Entity
public class Topics {

    @Id
    private String id;

    private String name;

    public Topics(){

    }
 getters and setters...
}

public interface TopicRepository extends CrudRepository<Topics, String> {

}
0
Rahul Wasnik