aime
aime

Reputation: 127

Hibernate: how to deal with Session in DAO to set associations properly?

I can't find a solution for setting an associations using DAO. It needs to be explain. There are 3 entities: Bank, Client and Account. Bank and Client have bidirectional many-to-many association, Client and Account have one-to-many association. There is GenericDAO interface which is implemented by each entity's DAO. As application is not-multithreading I decided to realize session-per-request "pattern" by opening and closing session in each method of DAO-interface implementations. Please take a look at the code. The problem is described below the code.

Bank POJO

@Entity
@Table(name = "bank")
public class Bank {

    private int bankID;
    private String bankName;
    private Set<Client> setOfClients;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "bank_id")
    public int getBankID() {
        return bankID;
    }

    public void setBankID(int bankID) {
        this.bankID = bankID;
    }

    @Column(name = "bank_name")
    public String getBankName() {
        return bankName;
    }

    public void setBankName(String bankName) {
        this.bankName = bankName;
    }

    @ManyToMany(mappedBy = "setOfBanks", fetch = FetchType.EAGER)
    public Set<Client> getSetOfClients() {
        return setOfClients;
    }

    public void setSetOfClients(Set<Client> setOfClients) {
        this.setOfClients = setOfClients;
    }
}**

Client POJO

@Entity
@Table(name = "client")
public class Client {

    private int clientID;
    private String firstName;
    private String secondName;
    private Set<Account> setOfAccounts;
    private Set<Bank> setOfBanks;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "client_id")
    public int getClientID() {
        return clientID;
    }

    public void setClientID(int clientID) {
        this.clientID = clientID;
    }

    @Column(name = "first_name")
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @Column(name = "second_name")
    public String getSecondName() {
        return secondName;
    }

    public void setSecondName(String secondName) {
        this.secondName = secondName;
    }

    @OneToMany(mappedBy = "clientID", cascade = {CascadeType.ALL})
    public Set<Account> getSetOfAccounts() {
        return setOfAccounts;
    }

    public void setSetOfAccounts(Set<Account> setOfAccounts) {
        this.setOfAccounts = setOfAccounts;
    }

    @ManyToMany(targetEntity = Bank.class, cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
    @JoinTable(
            name = "bank_client",
            joinColumns = {@JoinColumn(name = "client_id", nullable = false, referencedColumnName = "client_id")},
            inverseJoinColumns = {@JoinColumn(name = "bank_id", nullable = false, referencedColumnName = "bank_id")}
    )
    public Set<Bank> getSetOfBanks() {
        return setOfBanks;
    }

    public void setSetOfBanks(Set<Bank> setOfBanks) {
        this.setOfBanks = setOfBanks;
    }
}

ClientDAO

public class ClientDAO<Client> implements GenericDAO<Client>{

    private Session session;

    @Override
    public void saveEntity(Client entity) {
        try {
            session = SessionFactoryUtil.getSessionFactory().openSession();
            session.getTransaction().begin();
            session.save(entity);
            session.getTransaction().commit();
        } catch (HibernateException e) {
            session.getTransaction().rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
    }

    @Override
    public void deleteEntity(Client entity) {
        try {
            session = SessionFactoryUtil.getSessionFactory().openSession();
            session.getTransaction().begin();
            session.delete(entity);
            session.getTransaction().commit();
        } catch (HibernateException e) {
            session.getTransaction().rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }

    }

    @Override
    public void updateEntity(Object entity) {
        try {
            session = SessionFactoryUtil.getSessionFactory().openSession();
            session.getTransaction().begin();
            session.update(entity);
            session.getTransaction().commit();
        } catch (HibernateException e) {
            session.getTransaction().rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
    }

    @Override
    public Client getEntityByID(int id) {
        Client client = null;
        try {
            session = SessionFactoryUtil.getSessionFactory().openSession();
            session.getTransaction().begin();
            client = (Client) session.get(model.entity.Client.class, id);
        } catch (HibernateException e) {
            session.getTransaction().rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
        return client;
    }

    @Override
    public List<Client> getAllEntities() {
        List<Client> result = null;
        try {
            session = SessionFactoryUtil.getSessionFactory().openSession();
            session.getTransaction().begin();
            result = session.createQuery("from Client").list();
            session.getTransaction().commit();
        } catch (HibernateException e) {
            if (session != null) {
                session.getTransaction().rollback();
            }
            e.printStackTrace();
        } finally {
            session.close();
        }
        return result;
    }
}

BankDAO has similar methods realization but relating to bank-entity specification

Main-method

public class Main {
        public static void main(final String[] args) {

            ClientDAO<Client> clientDAO = new ClientDAO<Client>();
            BankDAO<Bank> bankDAO = new BankDAO<Bank>();

            Client client = clientDAO.getEntityByID(11);
            Bank bank = bankDAO.getEntityByID(3);

            Set<Bank> setOfBanks = client.getSetOfBanks();
            setOfBanks.add(bank);

            Set<Client> setOfClients = bank.getSetOfClients();
            setOfClients.add(client);
        }
}

I didn't mention that there is an entermediate table which contains values of foreign keys of Client-table anb Bank-table (it needs to reflect their many-to-many association). The result of main-method invokation supposed to be new added values in intermediate table (foreign keys of client and bank tables). It proves that the association is established. But when I call main-method happens nothing. I understand that when I setOfBanks.add(bank) and setOfClients.add(client) the objects are added in collections which don't relate to persistent objects because session is closed. And I don't know how to correctly open and close session in order to establish association within session. Hope I describe the issue clearly. I would really appreciate any reply.

Upvotes: 0

Views: 816

Answers (1)

David Levesque
David Levesque

Reputation: 22441

What you have implemented looks more like the session-per-operation anti-pattern than the session-per-request pattern imo. "Session-per-request" usually refers to a request in a client-server or Web application, where a request often involves multiple database operations.

It is harder to apply that pattern to a command-line application like yours, but the closest thing to a request in your case is probably the fact of running the app from the command-line. So I agree with nachokk that you should open your session at the beginning of the main method and close it at the end.

Upvotes: 1

Related Questions