-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Cascade multiple entities
PostPosted: Mon May 23, 2016 11:18 am 
Newbie

Joined: Thu May 19, 2016 6:29 am
Posts: 3
The ER diagram of the test db is :
Image

I reverse engineered the Hibernate entities(and made some changes to the cascade) which are as follows :
Account.java
Code:
    public class Account implements java.io.Serializable {

        private Integer id;
        private String reference;
        private BigDecimal balance;
        private String currency;
        private boolean valid;
        private String type;
        private Set transactionlegs = new HashSet(0);
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((reference == null) ? 0 : reference.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Account other = (Account) obj;
        if (reference == null) {
            if (other.reference != null)
                return false;
        } else if (!reference.equals(other.reference))
            return false;
        return true;
    }
.
.
    }

Account.hbm.xml

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated May 18, 2016 3:49:50 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
    <class name="com.bank.entity.Account" table="account"
        catalog="banktest" optimistic-lock="version">
        <id name="id" type="java.lang.Integer">
            <column name="Id" />
            <generator class="identity" />
        </id>
        <property name="reference" type="string">
            <column name="Reference" length="20" not-null="true" unique="true" />
        </property>
        <property name="balance" type="big_decimal">
            <column name="Balance" not-null="true" />
        </property>
        <property name="currency" type="string">
            <column name="Currency" length="3" not-null="true" />
        </property>
        <property name="valid" type="boolean">
            <column name="Valid" not-null="true" />
        </property>
        <property name="type" type="string">
            <column name="Type" length="20" />
        </property>
        <set name="transactionlegs" table="transactionleg" inverse="true"
            lazy="true" fetch="select">
            <key>
                <column name="AccountId" not-null="true" />
            </key>
            <one-to-many class="com.bank.entity.Transactionleg" />
        </set>
    </class>
</hibernate-mapping>

Transaction.java

Code:
public class Transaction implements java.io.Serializable {

    private Integer id;
    private String type;
    private String reference;
    private Date createdDate;
    private Date updatedDate;
    private Set transactionlegs = new HashSet(0);

@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((createdDate == null) ? 0 : createdDate.hashCode());
        result = prime * result + ((reference == null) ? 0 : reference.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Transaction other = (Transaction) obj;
        if (createdDate == null) {
            if (other.createdDate != null)
                return false;
        } else if (!createdDate.equals(other.createdDate))
            return false;
        if (reference == null) {
            if (other.reference != null)
                return false;
        } else if (!reference.equals(other.reference))
            return false;
        return true;
    }
.
.
}

Transaction.hbm.xml

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated May 17, 2016 1:56:15 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
    <class name="com.bank.entity.Transaction" table="transaction"
        catalog="banktest" optimistic-lock="version">
        <id name="id" type="java.lang.Integer">
            <column name="Id" />
            <generator class="identity" />
        </id>
        <property name="type" type="string">
            <column name="Type" length="20" not-null="true">
                <comment>e.g : transfer of funds from one account to other, cash
                    withdrawal</comment>
            </column>
        </property>
        <property name="reference" type="string">
            <column name="Reference" length="20" not-null="true" />
        </property>
        <property name="createdDate" type="timestamp">
            <column name="CreatedDate" length="19" not-null="true" />
        </property>
        <property name="updatedDate" type="timestamp">
            <column name="UpdatedDate" length="19" not-null="true" />
        </property>
        <set name="transactionlegs" table="transactionleg" inverse="true"
            lazy="true" fetch="select" cascade="save-update,delete">
            <key>
                <column name="TransactionId" not-null="true" />
            </key>
            <one-to-many class="com.bank.entity.Transactionleg" />
        </set>
    </class>
</hibernate-mapping>

Transactionleg.java

Code:
public class Transactionleg implements java.io.Serializable {

    private Integer id;
    private Account account;
    private Transaction transaction;
    private BigDecimal amount;
    private String type;
    private String currency;
    private byte leg;
    private boolean isValid;
    private Date createdDate;
    private Date updatedDate;
@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((account == null) ? 0 : account.hashCode());
        result = prime * result + ((amount == null) ? 0 : amount.hashCode());
        result = prime * result + ((createdDate == null) ? 0 : createdDate.hashCode());
        result = prime * result + ((currency == null) ? 0 : currency.hashCode());
        result = prime * result + leg;
        result = prime * result + ((transaction == null) ? 0 : transaction.hashCode());
        result = prime * result + ((type == null) ? 0 : type.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Transactionleg other = (Transactionleg) obj;
        if (account == null) {
            if (other.account != null)
                return false;
        } else if (!account.equals(other.account))
            return false;
        if (amount == null) {
            if (other.amount != null)
                return false;
        } else if (!amount.equals(other.amount))
            return false;
        if (createdDate == null) {
            if (other.createdDate != null)
                return false;
        } else if (!createdDate.equals(other.createdDate))
            return false;
        if (currency == null) {
            if (other.currency != null)
                return false;
        } else if (!currency.equals(other.currency))
            return false;
        if (leg != other.leg)
            return false;
        if (transaction == null) {
            if (other.transaction != null)
                return false;
        } else if (!transaction.equals(other.transaction))
            return false;
        if (type == null) {
            if (other.type != null)
                return false;
        } else if (!type.equals(other.type))
            return false;
        return true;
    }

Transactionleg.hbm.xml

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated May 17, 2016 1:56:15 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
    <class name="com.bank.entity.Transactionleg" table="transactionleg" catalog="banktest" optimistic-lock="version">
        <id name="id" type="java.lang.Integer">
            <column name="Id" />
            <generator class="identity" />
        </id>
        <many-to-one name="account" class="com.bank.entity.Account" fetch="select">
            <column name="AccountId" not-null="true" />
        </many-to-one>
        <many-to-one name="transaction" class="com.bank.entity.Transaction" fetch="select" cascade="save-update,delete">
            <column name="TransactionId" not-null="true" />
        </many-to-one>
        <property name="amount" type="big_decimal">
            <column name="Amount" not-null="true" />
        </property>
        <property name="type" type="string">
            <column name="Type" length="10" not-null="true" />
        </property>
        <property name="currency" type="string">
            <column name="Currency" length="3" not-null="true" />
        </property>
        <property name="leg" type="byte">
            <column name="Leg" not-null="true" />
        </property>
        <property name="isValid" type="boolean">
            <column name="IsValid" not-null="true" />
        </property>
        <property name="createdDate" type="timestamp">
            <column name="CreatedDate" length="19" not-null="true" />
        </property>
        <property name="updatedDate" type="timestamp">
            <column name="UpdatedDate" length="19" not-null="true" />
        </property>
    </class>
</hibernate-mapping>

Now, suppose there is a Transaction with 4 Transactionleg and each leg does some change to an Account. I wish to execute a single query, probably persist only the Transaction which auto-inserts the Transactionleg and also updates the Account :

Code:
Set<Transactionleg> transactionLegDbRecords = new HashSet<>();
        for (TransactionLeg transactionLeg : transactionLegs) {

            Transactionleg transactionleg = new Transactionleg(
                    transactionDbRecord, transactionLeg.getAmount().getAmount(),
                    (transactionLeg.getAmount().getAmount().signum() == -1 ? "DEBIT" : "CREDIT"),
                    transactionLeg.getAmount().getCurrency().getCurrencyCode(),
                    (byte) transactionLegs.indexOf(transactionLeg), true, timeStamp, timeStamp);

            transactionLegDbRecords.add(transactionleg);

            log.debug("Transactionleg is " + transactionleg);
        }

        transactionDbRecord.setTransactionlegs(transactionLegDbRecords);

        TransactionDao transactionDao = new TransactionDaoImpl();
        transactionDao.save(transactionDbRecord);

I'm unsure if my expectation is fair because :

    Logically/sensible at a database query level, I am uncomfortable with the main Account record being left at the mercy of the child updates
    How to do this in Hibernate for all the scenarios e.g: persist Account and let Transaction and Transactionleg be updated/created auto.
Of course, in all the cases, data consistency is must - one failure should cause rollback and keep all the entities intact.

What am I missing ?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.