Доступ к базе данных в Java прошел несколько этапов:
- во-первых, чистый JDBC
- проприетарные рамки
- стандарты, такие как EJB Entities и JDO
- Платформы OpenSource, такие как Hibernate и EclipseLink (в то время известные как TopLink)
Когда
JPA был наконец выпущен, казалось, мои желания сбылись. Наконец, из траншей появился стандарт для доступа к базам данных в Java. К сожалению, JPA не выполнил свои обещания по сравнению с Hibernate: например, у вас нет
Query by Example . Хуже того, в своей первой версии JPA не предоставляла простых функций, таких как
Criteria , поэтому даже простые запросы должны были реализовываться через JPQL и, следовательно, достигаться с помощью конкатенации строк. ИМХО, это полностью побежденные
цели ОРМ .
JPA2 на помощь
Наконец, JPA2 предоставляет что-то полезное в реальных приложениях. И все же, я чувствую, что все еще так много стандартного кода, чтобы написать простой
CRUD
DAO :
public class JpaDao<E, PK> { @PersistenceContext private EntityManager em; private Class<E> managedClass; private JpaDao(Class<E> managedClass) { this.managedClass = managedClass; } public void persist(E entity) { em.persist(entity); } public void remove(E entity) { em.remove(entity); } public E findById(PK id) { return em.find(managedClass, id); } }
Некоторые будут (и будут) возражать, что в таком случае использования нет необходимости в DAO: EntityManager просто нужно внедрить в класс обслуживания и использовать напрямую. Это может быть подходящей точкой зрения, но только когда нет запроса, как только вы выходите за рамки этого, вам необходимо разделить доступ к данным и бизнес-логику.
Код котельной в JPA2
Два простых варианта использования выделяют бесполезный шаблонный код в JPA 2: @NamedQuery и простые критерии. В первом случае вы должны получить указатель на именованный запрос через менеджер сущностей, а затем установить потенциальные параметры, например, так:
Query query = em.createNamedQuery("Employee.findHighestPaidEmployee");
Во втором случае вы должны реализовать свой собственный запрос с помощью CriteriaBuilder:
CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<Person> query = builder.createQuery(Person.class); Root<Person> fromPerson = query.from(Person.class); return em.createQuery(query.select(fromPerson)).getResultList();
ИМХО, эти строки кода ничего не приводят в таблицу и просто загромождают наш собственный код. Случайно, некоторое время назад, я нашел проект
Hades , продукт, основанный на этом заключении, и написал для вас простой код.
Spring Data JPA
Учитывая судьбу некоторых отличных OpenSource-проектов, у Hades дела шли намного лучше, поскольку он был перенесен в экосистему Spring под названием Spring Data JPA. Стандартно SDJ предоставляет DAO с расширенными функциями CRUD. Например, следующий интерфейс можно использовать как есть: [java] открытый интерфейс EmployeeRepository расширяет JPARepository [/ java] Учитывая некоторую магию Spring, реализация будет обеспечена во время выполнения следующими методами:
- void deleteAllInBatch ()
- void deleteInBatch (Iterable <Employee> entity)
- List <Employee> findAll ()
- List <Employee> findAll (сортировка по сортировке)
- void flush ()
- <S extends Employee> List <S> save (итерируемые <S> сущности)
- Сотрудник saveAndFlush (Сотрудник сущности)
- Страница <Сотрудник> findAll (Pageable Pageable)
- Iterable <Employee> findAll (сортировка по сортировке)
- длинный счет ()
- аннулировать удаление (ID ID)
- void delete (Iterable <? extends Employee> лица)
- void delete (сущность сотрудника)
- void deleteAll ()
- логическое существует (длинный идентификатор)
- Iterable <Employee> findAll ()
- Iterable <Employee> findAll (Итерируемые идентификаторы)
- Сотрудник findOne (длинный идентификатор)
- <S extends Employee> Iterable <S> save (Iterable <S> сущностей)
- <S расширяет Сотрудника> S сохранить (объект S)
Да, SDJ предоставляет вам общий DAO, как и многие другие платформы, но здесь подключение к базовой реализации обрабатывается этой платформой бесплатно. Для тех, кто не нуждается в них всех и предпочитает строгий минимум, вы также можете использовать следующую стратегию, где вам нужно выбрать методы из списка выше (и использовать аннотацию):
]@RepositoryDefinition(domainClass = Employee.class, idClass = Long.class) public interface EmployeeRepository { long count(); Employee save(Employee employee); }
Это конечно хорошо, но лучшее еще впереди. Помните два приведенных выше варианта использования, которые мы должны были написать сами? Первый просто обрабатывается добавлением неквалифицированного имени запроса в интерфейс следующим образом:
@RepositoryDefinition(domainClass = Employee.class, idClass = Long.class) public interface EmployeeRepository { ... Employee findHighestPaidEmployee(); }
Второй сценарий поиска всех сотрудников представлен в репозитории JPA. Но давайте на секунду представим, что у нас есть предложение WHERE, например, для имени. SDJ способен обрабатывать простые запросы на основе имени метода:
@RepositoryDefinition(domainClass = Employee.class, idClass = Long.class) public interface EmployeeRepository { ... List<Employee> findByLastname(String firstName); }
Пришлось кодировать только интерфейс и его методы: не было задействовано ни кода реализации, ни генерации метамодели! Не волнуйтесь, если вам нужно реализовать несколько сложных запросов, SDJ позволит вам связать вашу собственную реализацию.
Вывод
Если вы уже являетесь пользователем Spring, Spring Data JPA действительно (действительно!) Обязательно. Если это не так, вы можете протестировать его, чтобы увидеть его дополнительную ценность. ИМХО, SDJ — одна из причин, по которой JavaEE еще не убил Spring: он перекрыл часть впрыска, но шаблонный код все еще на каждом шагу. Эта статья не с практическими рекомендациями, а с тизером, чтобы позволить вам в SDJ. Вы можете найти источники для этой статьи
здесь , в формате Maven / Eclipse. Чтобы идти дальше:
- Документация Spring Data JPA
- Spring Data JPA Javadocs
Для тех, кто еще не в JPA, есть
Data JDBC ; для тех, кто намного выше этого (подумайте о больших данных); есть
Data Hadoop . Проверьте все
проекты Spring Data !