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#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...