我有一个使用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是从hibernate调用中检索的Account实体列表。在for循环中,使用 clientService.findById 方法中的hibernate调用从帐户中检索客户端实体。
这些是参与电话会议的课程:
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对象。
我的问题是如何使用hibernate优化循环内的clientService.findById?我觉得findById调用使循环过程变慢。
accountList通常包含7000多条记录,所以我需要类似预编译查询机制的东西,就像jdbc中的PreparedStatements一样。可以用hibernate做到这一点吗?
注意:通过删除不相关的部分简化了上面的代码,方法,变量和类名因隐私原因而变得虚假。如果您发现拼写错误,请在评论部分告诉我,因为我手动输入了代码。
答案 0 :(得分: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();
}
}
答案 1 :(得分:1)
我找到了最好的解决方案。我将查询表从Account和Client连接在一起的视图(VIEW_ACCOUNT_CLIENT),然后我为视图创建实体类(AccountClientView)并使用hibernate获取它,结果是哇,它大大提升了性能。使用真实代码,完成循环可能需要大约15-20分钟,但使用View,只需要8-10秒
@Entity
@Table(name = "VIEW_ACCOUNT_CLIENT")
public class AccountClientView implements Serializable {
...
}
答案 2 :(得分: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
实体不包含Client
,那么您应该有充分的理由。