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
(?, ?, ?)