Spring Data a vytváření dotazů pomocí entity manažera

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

Napsat komentář