アプリケーションが必要とするメモリを最小限に抑えるために、サービス クラスでどの注釈を使用すればよいかわかりません。
1 人の顧客による最大の合計支出を見つけたい顧客/注文のシナリオを考えてみましょう。合計で 100 万件の注文と 100 人の顧客があり、各顧客は 10,000 件の注文を行っています。
私が考えることができる最も簡単な例は次のとおりです。
public class MyService {
@Transactional(readOnly=true)
public int getMaxSpend() {
int maxSpend = 0;
List<Customer> customers = customerDao.findAll();
for(Customer customer : customers) {
List<Order> orders = orderDao.getOrders(customer);
for(Order order : orders) {
if(order.getTotal() > maxSpend) maxSpend = order.getTotal();
}
}
return maxSpend;
}
}
トランザクションは各顧客の注文の読み込みにまたがるので、最終的には休止状態のセッションに 100 万個のオブジェクトが存在することになると思いますが、これは理想とはほど遠いものです。Order
その顧客の反復が完了したら、顧客の注文ごとにガベージ コレクションを行うことで、メモリ内のインスタンスの数を最小限に抑えたいと考えています。
次の例では、顧客は注文のコレクションを参照しておらず、注文も顧客を参照していません。
public class MyService {
@Transactional(propagation=Propagation.NEVER)
public int getMaxSpend() {
int maxSpend = 0;
List<Customer> customers = getAllCustomers();
for(Customer customer : customers) {
int customerSpend = getCustomerSpend(customer);
if(customerSpend > maxSpend) maxSpend = customerSpend;
}
return maxSpend;
}
@Transactional(readOnly=true)
private List<Customer> getAllCustomers() {
return customerDao.findAll();
}
@Transactional(readOnly=true)
private int getCustomerSpend(Customer customer) {
int customerSpend = 0;
List<Order> orders = orderDao.getOrders(customer);
for(Order order : orders) {
customerSpend += order.getTotal();
}
return customerSpend;
}
}
残念ながら、jprofiler でメモリをプロファイリングすると、まだ 100 万個のインスタンスがOrder
ロードされています。プライベートメソッドはトランザクションに対応できないと思っていたので、休止状態の例外が発生することを期待していましたが、これは決して起こりませんでした。上記は正しいアプローチで、どういうわけかすでにトランザクションを開いていますか、それとも私の目標を達成する別の方法がありますか?