[jboss-user] [EJB 3.0] - EntityManager.merge() very slow compared to fetch-update-sto
twwwt
do-not-reply at jboss.com
Thu Nov 30 11:06:28 EST 2006
Hi all,
I played with this simple code in a session EJB and realised that the merge operation of EntityManager is very slow (more than one second):
| public void transfer(Account from, Account to, double value) throws AccountOverdrawException, IllegalArgumentException {
| try
| {
| to.deposit(value);
| em.merge(to);
| from.withdraw(value);
| em.merge(from);
|
| }
| catch (AccountOverdrawException e)
| {
| context.setRollbackOnly();
| throw e;
| }
| catch (IllegalArgumentException e)
| {
| context.setRollbackOnly();
| throw e;
| }
| }
|
After that, I tried this version which is much faster (about 10ms):
| public void transfer(Account from, Account to, double value) throws AccountOverdrawException, IllegalArgumentException {
| try
| {
| Account f = em.find(Account.class, from.getAccountID());
| Account t = em.find(Account.class, to.getAccountID());
| t.deposit(value);
| f.withdraw(value);
|
| }
| catch (AccountOverdrawException e)
| {
| context.setRollbackOnly();
| throw e;
| }
| catch (IllegalArgumentException e)
| {
| context.setRollbackOnly();
| throw e;
| }
| }
|
My first guess was that it might be slow because of cascaded merge of associated objects inside Account (see code below). But then I read in the EJB specification that by default there is no cascading, i.e., it has to be explicetly set in the annotations. Is there any other thing I'm currently not aware of that causes the difference.
Thanks,
Thorsten
| @Entity
| public class Account implements Serializable
| {
| private static final long serialVersionUID = 7443656659402964861L;
|
| private double balance;
| private long accountID;
| private Customer customer;
| private Bank bank;
|
| Account()
| {
| super();
| }
|
| public Account(Customer owner)
| {
| this.customer = owner;
| }
|
| @Id
| @GeneratedValue(strategy = GenerationType.SEQUENCE)
| public long getAccountID()
| {
| return accountID;
| }
|
| void setAccountID(long newID)
| {
| this.accountID = newID;
| }
|
| @Column
| public double getBalance()
| {
| return balance;
| }
|
| void setBalance(double newBalance)
| {
| this.balance = newBalance;
| }
|
| @ManyToOne
| public Bank getBank()
| {
| return bank;
| }
|
| public void setBank(Bank bank)
| {
| this.bank = bank;
| }
|
| @ManyToOne
| public Customer getCustomer()
| {
| return customer;
| }
|
| void setCustomer(Customer newCustomer)
| {
| this.customer = newCustomer;
| }
|
| /**
| * @param amount Deposit the given amount to the account.
| * @throws IllegalArgumentException if the given amount is less than zero.
| */
| public void deposit(double amount)
| {
| if (amount < 0) throw new IllegalArgumentException("Deposit of negative amount is not allowed");
| setBalance(getBalance() + amount);
| }
|
| /**
| * @param amount Withdraw the given amount from the account.
| * @throws IllegalArgumentException if the given amount is less than zero.
| * @throws AccountOverdrawException in case given amout is greather than acount balance.
| */
| public void withdraw(double amount) throws AccountOverdrawException
| {
| if (amount < 0) throw new IllegalArgumentException("Withdraw of negative amount is not allowed");
| if (amount > balance) throw new AccountOverdrawException("The operation would lead to overdrawing the account and was rejected.");
| setBalance(getBalance() - amount);
| }
| }
|
Note that Customer in turn has a list of Account(s) and Bank has a list of Customer(s) and Account(s), whereby the fetch type of those properties is set to lazy.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3990132#3990132
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3990132
More information about the jboss-user
mailing list