2

在 JPA 中,实体是带有很好注释的普通 Java 对象。但是我还没有找到与它们和数据库交互的好方法。

在我当前的应用程序中,我的基本设计始终是将基于序列的 id 作为主键,因此我通常必须通过 PK 以外的其他属性查找实体。

对于每个实体,我都有一个无状态的 EJB

@Stateless
public class MyEntApiBean implements MyEntApi {


@PersistenceContext(unitName = "xxx") @Inject EntityManager entityManager;

查询方法都是一些变化

/**
 * @return A List of all MyEnts that have some property
 * @param someProp some property
 */
public List<MyEnt> getAllMyEntsFromProp(final String someProp) {

    try {
        final Query query = entityManager.createQuery("select me from MyEnt me where me.someProp = :someProp");
        query.setParameter("someProp", someProp);
        return query.getResultList();
    } catch(final NoResultException nre) {
        log.warn("No MyEnts found");
    }
    return new ArrayList<MyEnt>();
}

所以:

  1. 我真的很讨厌在 EJB 中使用这些方法,因为它们似乎属于实体本身,而 EJB 本地接口让我很恼火。

  2. 我讨厌我在每个方法中都有“try、createQuery、getResultList、catch、log、return”的重复(主要是Java中没有闭包或“with语句”或类似的结果)。

是否有人建议以更好的方式与解决我的一个或两个问题的实体和数据库进行交互?

我目前正在考虑使用泛型和反射做一些基本方法,以获得一些通用查询方法来减少重复(问题 2)(我稍后会提出一个原型供审查)。

谢谢,安德斯

4

6 回答 6

4

试试缝。查询对象为您完成大部分工作,并且它们很容易扩展。或者,您总是可以实现类似的模式。

一般来说,Seam 做了很多有用的东西来弥合 JPA 与您的视图和业务层之间的差距。您不必使用 JSF 来使 Seam 有用。

于 2008-10-07T10:55:07.770 回答
3

你是不必要的冗长。一方面,getResultList() 在没有返回任何行时不会抛出异常(至少在 Eclipse 或 Toplink 中不会——我无法想象另一个提供者会有什么不同)。getSingleResult() 会, getResultList() 不会。此外,您可以使用构建器模式:

@SuppressWarnings("unchecked")
public List<MyEnt> getAllMyEntsFromProp(final String someProp) {
  return entityManager.createQuery("select me from MyEnt me where me.someProp = :someProp")
    .setParameter("someProp", someProp);
    .getResultList();
}

如果有任何结果,则应该足以返回结果列表,如果没有,则返回空列表。有两点需要注意:

  1. @SuppressWarnings("unchecked") 是不必要的,但在将非泛型 List 结果从 getResultList() 转换为泛型 List 时,它消除了其他不可避免的警告;和

  2. 可能值得用 MyEnt 上的 @NamedQuery 替换 createQuery() 调用(通常)。一方面,这将启用部署时验证和其他有用的东西。

它相当简洁和完整。

于 2008-10-07T14:35:27.623 回答
1

如果您进行大量文本搜索,也许您还应该考虑一些索引框架,例如Compass
我不知道它是否适合您的应用程序,但如果适合,它可以同时改进代码设计和性能。

于 2008-10-07T11:46:12.207 回答
1

我实际上正在使用Seam。查询对象建议让我找到了 Hibernates Criteria queries (Query By Example)功能。这似乎非常接近我正在寻找的东西。

也许在一个基类中,并带有一些泛型......?

于 2008-10-07T12:31:33.317 回答
1

嗬嗬!

这是我的单一结果版本(我在桌面 JPA 应用程序中使用它和 TopLink 基本要素):

public class JPA {
  @SuppressWarnings ("unchecked")
  public static <T> T querySingle(
      EntityManager em, 
      Class<T> clazz, 
      String namedQuery, 
      Pair... params) 
  {
    Query q = em.createNamedQuery(namedQuery);
    for (Pair pair : params) {
      q.setParameter(pair.key, pair.value);      
    }
    List<T> result = q.getResultList();
    if ( result.size() == 0 ) {
      return null;
    }
    if ( result.size() == 1 ) {
      return result.get(0);
    }
    throw new 
      IllegalStateException(
        "To many result rows for query: " 
         + namedQuery 
         + " where " 
         + Arrays.toString(params));
  }

  public static class Pair {
    String key;
    Object value;

    public static Pair param (String key, Object value) {
      return new Pair (key, value);
    }

    public Pair (String key, Object value) {
      this.key = key;
      this.value = value;
    }

    @Override
    public String toString() {
      return key + "=" + value;
    }
  }
}

以及用法:

import static org.sepix.JPA.*;
...

String id = ...
Customer customer = querySingle (em, Customer.class, 
                      "Customer.findByID", Pair.param ("id", id));

或者:

String inquiryID = ...
Boolean current = Boolean.TRUE;
Inquiry inq = querySingle (em, Inquiry.class, 
                      "Inquiry.findCurrent", 
                      Pair.param ("inquiry", inquiryID),
                      Pair.param ("current", current));

最好的问候,乔希。

于 2009-10-19T07:50:50.480 回答
0

我更喜欢使用 Spring 的 JpaDaoSupport,它有助于处理 JPA。一个很好的例子是这里http://github.com/rafalrusin/jpaqb/blob/master/src/test/java/jpaqb/CarDao.java

一个很好的逻辑分离是有一个 DAO 类(数据访问对象)和 DTO(数据传输对象)。DAO 通常包含所有必需的查询,而 DTO 是具有字段的实体。

于 2010-02-04T20:29:04.467 回答