Reputation: 127
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
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