To jak Spring Data zjednodušuje práci s databází jsem ukázal v příspěvku Spring Data a získání metod pro základní operace nad tabulkou. V tomto příspěvku si ale ukážeme jak vytvářet sql příkazy pomocí entity manažera (EntityManager).
Vytvoříme si třídu s názvem OrderRepository a označíme ji jako repository anotací @Repository
(org.springframework.stereotype.Repository).
@Repository class OrderRepository {}
Necháme si Springem injektovat EntityManager.
@PersistenceContext private lateinit var entityManager: EntityManager
K vytváření se používá CriteriaBuilder
a CriteriaQuery
CriteriaBuilder
Rozhraní, které se používá pro vytváření criteria queries a výroků. Vytváří predikáty (výroky), které tvoří podmínky dotazu. K vytváření predikátů poskytuje metody equals(), notLike(), exists(), and(), or(), not(), conjuction(), disjunction(), greaterThan(), lessThanOrEqualTo(), between() …
CriteriaQuery
Představuje dotaz. CriteriaQuery obsahuje řadu metod pro vytváření dotazů: select(), where(), groupBy(), orderBy(), distinct(), having(), …
Zde jsou ukázky vytváření sql dotazů a jak jsou následně vygenerovány (volba spring.jpa.show-sql: true
v application.properties
).
findAll
fun findAll(): List<Order> { val criteriaBuilder: CriteriaBuilder = entityManager.criteriaBuilder val criteriaQuery: CriteriaQuery<Order> = criteriaBuilder.createQuery(Order::class.java) val root: Root<Order> = criteriaQuery.from(Order::class.java) val typedQuery: TypedQuery<Order> = entityManager.createQuery(criteriaQuery) val resultList: MutableList<Order> = typedQuery.resultList return resultList } select order0_.id as id1_4_, order0_.identifier as identifi2_4_, order0_.sum as sum3_4_ from t_order order0_
findByIdentifier
fun findByIdentifier(uuid: UUID): Order? { val criteriaBuilder: CriteriaBuilder = entityManager.criteriaBuilder val criteriaQuery: CriteriaQuery<Order> = criteriaBuilder.createQuery(Order::class.java) val root: Root<Order> = criteriaQuery.from(Order::class.java) criteriaQuery.select(root) criteriaQuery.where(criteriaBuilder.equal(root.get(Order_.identifier), uuid)) try { val typedQuery = entityManager.createQuery(criteriaQuery) val singleResult: Order = typedQuery.singleResult return singleResult } catch (nre: NoResultException) { return null } } select order0_.id as id1_4_, order0_.identifier as identifi2_4_, order0_.sum as sum3_4_ from t_order order0_ where order0_.identifier=?
deleteAll
fun deleteAll() { val query: Query = entityManager.createQuery("delete from Order") query.executeUpdate() } delete from t_order
delete
fun delete(order: Order) { // Pozor na detached instance exception - https://stackoverflow.com/questions/17027398/java-lang-illegalargumentexception-removing-a-detached-instance-com-test-user5 entityManager.remove(if (entityManager.contains(order)) order else entityManager.merge(order) ) } delete from t_order where id=?
save
fun save(order: Order) { // Pozor na No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call // Řešením je přidat @Transactional do OrderRepository entityManager.persist(order) } select nextval ('t_order_seq') insert into t_order (identifier, sum, id) values (?, ?, ?)