如何有效地使用PreparedStatement?

时间:2016-02-08 17:44:42

标签: java jpa prepared-statement

我喜欢使用DAO模式,并且有一个类可以为特定的表和JPA实体执行所有SQL请求。我有例如:

public class MyDao {

    @PersistenceContext(name = "mycontext")
    private EntityManager entityManager;

    public List<MyEntity> find(String code)  {

        return getEntityManager()
            .createQuery("FROM MyEntity e WHERE e.code = :code")
            .setParameter("code", code)
            .getResultList();

    }

}

但我也知道我们可以使用静态方法直接在实体类上使用命名查询(我不喜欢这种方式):

@Entity
@Table
@NamedQueries({
    @NamedQuery(name = "find", query = "FROM MyEntity e WHERE e.code = :code")
})
public class MyEntity {

    ...

    public static List<MyEntity> find(EntityManager entityManager, String code) {

        return entityManager.createNamedQuery("find", MyEntity.class)
            .setParameter("code", code)
            .getResultList();

    }

}

其中一种方法比另一种更好吗?如果我想在同一个事务中执行相同的SQL查询数千次,这两种方法是否都在JPA内存(或其他地方)保留了预处理语句?在这种情况下,这似乎是一种很好的做法。我认为第二种方法是因为它是静态的而不是第一种方法。我错了吗 ?

1 个答案:

答案 0 :(得分:2)

通过@NamedQuery进行声明定义查询的优势在于,如果您在persistence.xml 中使用JPA非启用它,它们将被预编译,可以缓存在辅助缓存中并在启动时进行语法验证-hibernate特定API

因此,如果您计划仅使用JPA执行查询,通常最好使用NamedQuery并缓存查询。

因此,对于使用hibernate的JPA,您可以执行以下操作:

            @NamedQuery(name="AbstractBaseQuestion.findAllInstancesByGroupID", query="SELECT q FROM AbstractBaseQuestion q WHERE q.isTemplate = FALSE", hints={@QueryHint(name="org.hibernate.cacheable", value="true"),@QueryHint(name="org.hibernate.cacheMode", value="NORMAL"),}),

在hibernate的persistence.xml中,您可以在启动时验证这些@NamedQueries:

      <property name="hibernate.hbm2ddl.auto" value="validate"/>

现在,如果您使用Hibernate Session API,您建议的第一个方法可以进行缓存和预编译。我想EclipseLink和其他ORM上有等价物,但此时你正在使用非JPA功能,这些功能可能会使一个JPA实现难以实现。

如果您没有执行额外的实现特定工作,您的查询将不会被缓存,您将支付性能损失。

我希望有所帮助。