官术网_书友最值得收藏!

The service layer

The goal of the book being to discuss the performance and not how to write a Java EE application, we will not detail the whole service layer here. However, to ensure a common knowledge of what we are dealing with, we will illustrate the code with one service.

We are using JTA 1.2 with JPA 2.2 to establish a link between our database and the Java model. The QuoteService bean, responsible for managing the Quote persistence, can therefore look like the following:

@Transactional
@ApplicationScoped
public class QuoteService {
@PersistenceContext
private EntityManager entityManager;

public Optional<Quote> findByName(final String name) {
return entityManager.createQuery("select q from Quote q where
q.name = :name"
, Quote.class)
.setParameter("name", name)
.getResultStream()
.findFirst();
}

public Optional<Quote> findById(final long id) {
return Optional.ofNullable(entityManager.find(Quote.class, id));
}

public long countAll() {
return entityManager.createQuery("select count(q) from Quote
q"
, Number.class)
.getSingleResult()
.longValue();
}

public Quote create(final Quote newQuote) {
entityManager.persist(newQuote);
entityManager.flush();
return newQuote;
}

// ... other methods based on the same model
}

JPA may or may not be used in a transactional context, depending on the kind of operation you do. When you read data, you can often do it without any transaction until you need some lazy loading. However, when you write data (insert/update/delete entities), JPA requires a running transaction to be able to execute the action. This is to ensure consistency of data but also has some implications on the code. To respect that requirement, and have an active transaction, we use @Transactional on methods instead of relying on Enterprise Java Bean 3.2 (EJB 3.2), so we can reuse the power of CDI (@ApplicationScoped, for instance, which will avoid creating a new instance per injection).

Our finders are very simple and directly use the EntityManager API. The only new thing Java 8 brings us in this code is the ability to wrap the result with Optional which offers a programmatic way to deal with the presence or absense of the entity instead of relying on a null check. Concretely, the caller can use our finder this way:

final int quoteCount = getCustomer().getCountFor("myquote");
final double quotesPrice = quoteService.findByName("myquote")
.map(quote -> quote.getValue() * quoteCount)
.orElse(0);

This kind of code hides the conditional branches behind a fluent API, which makes it more expressive and readable, while the lambdas stay small enough.

Finally, we used inline queries in this code, not static ones like in the @NamedQuery API.

主站蜘蛛池模板: 临邑县| 五峰| 沙湾县| 晋中市| 龙山县| 贵阳市| 刚察县| 左权县| 舒兰市| 铁力市| 克什克腾旗| 运城市| 阿瓦提县| 霸州市| 雷山县| 璧山县| 潼关县| 汕尾市| 诸暨市| 中阳县| 浪卡子县| 班戈县| 花垣县| 香河县| 革吉县| 和平县| 车险| 宣汉县| 江西省| 廊坊市| 山东省| 通渭县| 阜新市| 绥德县| 西峡县| 云林县| 广饶县| 志丹县| 洮南市| 灌阳县| 婺源县|