0

spring+hibernateを使用して構築されたJavaWebアプリケーションがあります。

私はこのようなコードを持っています:

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は、休止状態の呼び出しから取得したアカウントエンティティのリストです。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はSpringBeanオブジェクトです。

私の質問は、休止状態でループ内のclientService.findByIdを最適化する方法ですか?findById呼び出しにより、ループプロセスが遅くなるように感じます。

accountListには通常7000以上のレコードが含まれているため、jdbcのPreparedStatementsのようなプリコンパイルされたクエリメカニズムのようなものが必要です。Hibernateでこれを行うことは可能ですか?

注:上記のコードは、無関係な部分を削除することで簡略化されています。メソッド、変数、クラス名は、プライバシー上の理由から架空のものになっています。コードを手動で入力したので、タイプミスを見つけた場合は、コメントセクションでお知らせください。

4

3 に答える 3

1

Hibernate / JPAでは、Hibernateクエリ言語/ JPAクエリ言語を使用してクエリを記述し、NamedQueriesを作成できます。NamedQueryはサーバーの起動時にコンパイルされるため、ある種のプリペアドステートメントのように考えることができます。

1つのクエリですべてのエンティティインスタンスを取得できる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 に答える
1

最善の解決策を見つけました。テーブルAccountとClientから列を選択するクエリをビュー(VIEW_ACCOUNT_CLIENT)に入れ、ビューのエンティティクラス(AccountClientView)を作成し、休止状態を使用してフェッチしました。結果はすごいです。パフォーマンスが大幅に向上します。実際のコードを使用すると、ループが完了するまでに約15〜20分かかる場合がありますが、Viewを使用すると、8〜10秒しかかかりません。

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

    ...

}
于 2013-04-01T09:42:52.637 に答える
0

何を達成したいのか明確ではありません。ループでサービスコールを行うことはありません。使ってみませんNamedQueryか?Clients指定されたに添付されているすべてを取得してから、Accountsそのリストを繰り返し処理しClientsます。

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

しかし、それは本当にビジネス要件に依存します!また、なぜあなたはただ電話しないのか私にはわかりません:

Client client = account.getClient();

すでにフェッチされているクライアントを使用してaccountListをロードすることをお勧めします。熱心なフェッチを使用するか、joinをフェッチします。Accountエンティティにが含まれていない場合Clientは、非常に正当な理由があります。

于 2013-03-27T11:28:18.237 に答える