0

我有一个使用 spring+hibernate 构建的 java web 应用程序。

我有这样的代码:

for (Account account : accountList){

    Client client = clientService.findById(account.getFkClient());  // fkClient is foreign key to Client

    if (client != null) {
        ...
        anObject.setName(client.getName());
        anObject.setAccountNo(account.getAccountNo());  
        ...
    }
    else {
        ...
        anObject.setAccountNo(account.getAccountNo());
        ...
    }

    ...
}

accountList 是从休眠调用中检索到的 Account 实体的列表。在 for 循环中,使用clientService.findById方法中的休眠调用从帐户中检索客户端实体。

这些是调用所涉及的类:

public class ClientService implements  IClientService {
    private IClientDAO clientDAO;

    ...

    @Override
    public Client findById(Long id) throws Exception {
        return clientDAO.findById(id);
    }
}

public class ClientDAO extends AbstractHibernateDAO<Client, Long> implements IClientDAO {

    @Override
    public Client findById(Long id) throws Exception {
        return super.findById(id);
    }
}

public class AbstractHibernateDAO<T,Y extends Serializable> extends HibernateDaoSupport {

    protected Class<T> domainClass = getDomainClass();

    private Class<T> getDomainClass() {
        if (domainClass == null) {
            ParameterizedType thisType = (ParameterizedType) getClass().getGenericSuperclass();
            domainClass = (Class<T>) thisType.getActualTypeArguments()[0];
        }
        return domainClass;
    }

    public T findById(final Y id) throws SystemException {
        return (T) this.execute(new HibernateCallback<T>() {

            @Override
            public T doInHibernate(Session session) throws HibernateException, SQLException {
                return (T) session.get(domainClass, id);
            }
        });
    }
}

注意:clientService 和 clientDAO 是 spring beans 对象。

我的问题是如何使用休眠优化循环内的clientService.findById?我觉得 findById 调用使​​循环过程变慢。

accountList 通常包含 7000+ 条记录,所以我需要类似 jdbc 中的 PreparedStatements 之类的预编译查询机制。可以用休眠来做到这一点吗?

注意:上面的代码已经通过删除不相关的部分进行了简化,出于隐私原因,方法、变量和类名都是虚构的。如果您发现错字,请在评论部分告诉我,因为我手动输入了代码。

4

3 回答 3

1

我找到了最好的解决方案。我把从表 Account 和 Client 中选择列的查询合并到一个视图 (VIEW_ACCOUNT_CLIENT) 中,然后我为视图创建实体类 (AccountClientView) 并使用 hibernate 获取它,结果是哇,它大大提高了性能。使用真实代码,大概需要 15-20 分钟才能完成循环,而使用 View,只需 8-10 秒

@Entity
@Table(name = "VIEW_ACCOUNT_CLIENT")
public class AccountClientView implements Serializable {

    ...

}
于 2013-04-01T09:42:52.637 回答
1

在 Hibernate/JPA 中,您可以使用 Hibernate 查询语言/JPA 查询语言编写查询并创建 NamedQueries。NamedQuery 在服务器启动时编译,因此您可以将其视为某种准备好的语句。

您可以尝试编写 HQL 查询,该查询可以通过单个查询获取所有实体实例。

我将在 JPQL 中为您提供示例,但您也可以使用 HQL 编写它。

@NamedQueries({
    @NamedQuery(name = "QUERY_BY_ID",
    query = "SELECT u from SomeEntity se WHERE se.id IN (:idList)"),
})
class SomeEntity {
}

class SomeEntityDao {
    public List<SomeEntity> findIdList(List<Long> idList) {
        Query query = entityManager.createNamedQuery("QUERY_BY_ID");
        query.setParameter("idList", idList);

        return query.getResultList();
    }
}
于 2013-03-27T11:27:26.680 回答
0

目前尚不清楚您想要实现什么。我不会循环进行服务调用。你为什么不使用一个NamedQuery?检索所有Clients附加到给定的Accounts,然后遍历该列表Clients

SELECT c from Client c JOIN c.account a WHERE a.id IN (:accounIds)

但这真的取决于业务需求!我也不清楚你为什么不打电话:

Client client = account.getClient();

您可能希望使用已获取的客户端加载您的 accountList。使用急切获取或fetch join。如果Account实体不包含 a Client,您应该有一个很好的理由。

于 2013-03-27T11:28:18.237 回答