Reputation: 127
I have 2 problems with data insertion into MySQL-tables throug Hibernate. There are 4 tables: Client, Account, Bank and Bank_Client. Client sets many-to-many association with Bank and one-to-many with Account. Bank_Client is intermediate join table betwen Client and Bank. Here it is issues:
a. If I save clientA and clientB only (take a look on Main.java) then there is only their properties' values are saved in tables. I pointed out cascade attribute in @ManyToMany and, If I understand correctly, it obliges save() to persist all the entities on which client-entity has references. But it doesn't. If I save all the objects(clientA, clientB, bankA, bankB, accountAClientA, accountBClientA) - everything works out. But the question - how to save all the referenced objects by saving the client-entity only;
b. In any abovementioned cases the data are not saved in Bank_Account.
I would appreciate any pieces of advice. Thank you in advance.
CREATE TABLE client(client_id INT(3) AUTO_INCREMENT,
first_name VARCHAR(15) NOT NULL,
second_name VARCHAR(15) NOT NULL,
PRIMARY KEY(client_id));
CREATE TABLE account(account_id INT(3) AUTO_INCREMENT,
account_number VARCHAR(12) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
currency VARCHAR(3) NOT NULL,
client_id INT(3) NOT NULL,
PRIMARY KEY(account_id),
FOREIGN KEY(client_id) REFERENCES client(client_id));
CREATE TABLE bank(bank_id INT(3) AUTO_INCREMENT,
bank_name VARCHAR(15) NOT NULL,
PRIMARY KEY(bank_id));
CREATE TABLE bank_client(client_id INT(3) NOT NULL,
bank_id INT(3) NOT NULL,
PRIMARY KEY(client_id, bank_id),
FOREIGN KEY(client_id) REFERENCES client(client_id),
FOREIGN KEY(bank_id) REFERENCES bank(bank_id));
Account.java
@Entity
@Table(name = "account")
public class Account {
private int accountID;
private String accountNumber;
private float amount;
private String currency;
private Client clientID;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "account_id")
public int getAccountID() {
return accountID;
}
public void setAccountID(int accountID) {
this.accountID = accountID;
}
@Column(name = "account_number")
public String getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
@Column(name = "amount")
public float getAmount() {
return amount;
}
public void setAmount(float amount) {
this.amount = amount;
}
@Column(name = "currency")
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "client_id")
public Client getClientID() {
return clientID;
}
public void setClientID(Client clientID) {
this.clientID = clientID;
}
}
Bank.java
@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")
public Set<Client> getSetOfClients() {
return setOfClients;
}
public void setSetOfClients(Set<Client> setOfClients) {
this.setOfClients = setOfClients;
}
}
Client.java
@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")
public Set<Account> getSetOfAccounts() {
return setOfAccounts;
}
public void setSetOfAccounts(Set<Account> setOfAccounts) {
this.setOfAccounts = setOfAccounts;
}
@ManyToMany(targetEntity = Bank.class, cascade = {CascadeType.ALL})
@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;
}
}
Main.java
public class Main {
public static void main(final String[] args) throws Exception {
Session session = SessionFactoryUtil.getSessionFactory().openSession();
Bank bankA = new Bank();
Bank bankB = new Bank();
Client clientA = new Client();
Client clientB = new Client();
Account accountAClientA = new Account();
Account accountBClientA = new Account();
bankA.setBankID(1);
bankA.setBankName("Deutch Bank AG");
bankA.setBankID(2);
bankB.setBankName("Barclays");
clientA.setClientID(1);
clientA.setFirstName("Alex");
clientA.setSecondName("Modoro");
clientB.setClientID(2);
clientB.setFirstName("Fedor");
clientB.setSecondName("Fokin");
accountAClientA.setAccountID(1);
accountAClientA.setAccountNumber("123456789120");
accountAClientA.setAmount(12000.00f);
accountAClientA.setCurrency("USD");
accountAClientA.setClientID(clientA);
accountBClientA.setAccountID(2);
accountBClientA.setAccountNumber("123456789156");
accountBClientA.setAmount(56020.00f);
accountBClientA.setCurrency("EUR");
accountBClientA.setClientID(clientA);
HashSet<Account> setOfAccountsClientA = new HashSet<Account>();
HashSet<Bank> setOfBanksClientA = new HashSet<Bank>();
HashSet<Account> setOfAccountsClientB = new HashSet<Account>();
HashSet<Bank> setOfBanksClientB = new HashSet<Bank>();
HashSet<Client> setOfClientsBankA = new HashSet<Client>();
HashSet<Client> setOfClientsBankB = new HashSet<Client>();
setOfAccountsClientA.add(accountAClientA);
setOfAccountsClientA.add(accountBClientA);
setOfBanksClientA.add(bankA);
setOfBanksClientA.add(bankB);
setOfClientsBankA.add(clientA);
setOfClientsBankA.add(clientB);
try {
session.getTransaction().begin();
// session.save(bankA);
// session.save(bankB);
session.save(clientA);
session.save(clientB);
// session.save(accountAClientA);
// session.save(accountBClientA);
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
SessionFactoryUtil.java
public class SessionFactoryUtil {
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;
private static ServiceRegistryBuilder registryBuilder;
private static SessionFactory buildSessionFactory() {
try {
Configuration configuration = new Configuration().configure();
registryBuilder = new ServiceRegistryBuilder().applySettings(configuration.getProperties());
serviceRegistry = registryBuilder.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (HibernateException e) {
e.printStackTrace();
}
return sessionFactory;
}
public static SessionFactory getSessionFactory() {
return buildSessionFactory();
}
public static void closeSessionFactory() {
if (sessionFactory != null) {
sessionFactory.close();
}
}
}
Upvotes: 0
Views: 67
Reputation: 340
To answer your question. To make cascading work you need to set all related objects to each other. You're not adding any of Banks to Clients. I suppose you should have method that adds Bank to Client's setOfBanks, and do clientA.addBank(bankA) before saving clientA.
And you really need to think about how your objects related to each other. In normal world you got the bank first, then people become clients of the bank and open their accounts in it. So bank should not be saved by cascading. It should already exist before saving client.
Upvotes: 1