2015-06-17 5 views
4

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

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

} 

Но потом весна не создала для него компонент.

Как это сделать?

Спасибо!

+1

Если вы используете пружинные ботинки, то вы определенно должны использовать пружинные загрузки JPA. Я думаю, что это лучший вариант. Вам даже не нужно будет писать класс DAO. – pmverma

ответ

10

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

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 и весной должен делать все остальное при условии, Foobar имеет свойство с именем CreatedDate

List<Foobar> findByCreatedDateGreaterThan(Date date); 

Для справки о том, как Spring может генерировать запросы на основе имени методы посмотреть http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation

+0

Ваша ссылка привела меня к http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query, который, на мой взгляд, является лучшим подходом для того, чтобы быть более легким для чтения и более явным. Отличный ответ! –

0

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

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

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

+0

Работает @Repository на интерфейсе. Поэтому тот факт, что это не конкретный класс, не имеет к этому никакого отношения. Очевидно, что здесь играет роль «не интерфейс», но почему? –

1

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

enter image description here Снимок экрана из Baeldung: Introduction to Spring.

Here - ссылка на документацию. Обратите внимание на «table 4. Supported keywords inside method names», который можно использовать для создания методов интерфейса, чье имя передает информацию генератору кода о том, какой запрос создать (см. Часть таблицы ниже).

enter image description here

+0

Имена методов могут быть довольно длинными ... –

0

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

@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

Зачем вам перебирать список, когда findAll дает вам список? – boutta

Смежные вопросы