使用级联属性,多对多关联无法正常工作

时间:2014-08-26 19:13:10

标签: java mysql hibernate many-to-many one-to-many

通过Hibernate将数据插入MySQL表有两个问题。有4个表: 客户,账户,银行和Bank_Client。客户与银行设置多对多关联,与账户设置一对多关联。 Bank_Client是Client和Bank之间的中间连接表。这是问题:

a。如果我只保存clientA和clientB(看看Main.java),那么只有它们的属性的值保存在表中。我在@ManyToMany中指出了cascade属性,如果我理解正确的话,它要求save()持久保存客户端实体引用的所有实体。但事实并非如此。如果我保存所有对象(clientA,clientB,bankA,bankB,accountAClientA,accountBClientA) - 一切都会成功。但问题是 - 如何通过仅保存客户端实体来保存所有引用的对象;

b。在上述任何情况下,数据都不会保存在Bank_Account中。

我很感激任何建议。提前谢谢。

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();
        }
    }

}

1 个答案:

答案 0 :(得分:1)

回答你的问题。要进行级联工作,您需要将所有相关对象相互设置。您没有向客户添加任何银行。我想你应该有方法将Bank添加到Client的setOfBanks,并在保存clientA之前执行clientA.addBank(bankA)。

你真的需要考虑你的对象如何相互关联。在正常的世界里,你首先得到银行,然后人们成为银行的客户并在其中开立账户。所以银行不应该通过级联来保存。在保存客户端之前它应该已经存在。