【问题标题】:How to map foreign key relations in hibernate如何在hibernate中映射外键关系
【发布时间】:2013-09-09 13:15:15
【问题描述】:

我有如下客户类和地址类: Customer 类中的 officeAddressId、homeAddressId 和 secondaryAddressId 用于表中的外键映射。

  public class customer implements serializable
    {
    private static final long serialVersionUID= -5830229553758180137L;
    int age;
    String officeAddressId= null;
    String homeAddressId= null;
    String secondaryAddressId= null;
    }

public class Address implements serializable
{
        private static final long serialVersionUID= -5130229553758180137L;
        private String              addressId           = null;
    private String              addressLine         = null;
    private String              cityName            = null;
    private String              stateName           = null;
    private String              countryName         = null;
    private String              pincode             = null;
}

我的数据库表是直截了当的:

CREATE TABLE customer
(
customerID varchar(40) primary key,
officeAddressId varchar(40),
homeAddressId varchar(40),
secondaryAddressId varchar(40),
age int 
);

CREATE TABLE Address
(
addressID varchar(40) primary key,
addressLine varchar(40),
cityName varchar(40),
stateName varchar(40),
countryName varchar(40),
pincode varchar(10),
);

我在服务层创建地址对象(家庭、办公室和次要联系人的地址 1 的 3 个对象)和客户对象并打开交易。我不确定应该如何在 hbm 映射文件中给出外键关系,以及如何保存这四个对象(3 个地址对象和 1 个客户对象)以及外键关系以何种顺序正确保存在数据库中。

提前谢谢....

【问题讨论】:

  • 这是Customer(应该大写)和Address之间的many-to-one关系。在Customer 类中,将String officeAddressId 更改为Address officeAddress
  • 我现在不知道您将在数据库中放入多少数据,但您的表中有一些冗余。因为对于每个地址,您都保存了城市相应的州、PIN 码和国家名称。您可以使用密码和国家名称作为键创建另一个表。或者,如果它不是世界范围内的应用程序,您的创建 - 只是密码。

标签: java hibernate


【解决方案1】:

这里有一个更适合您的问题的答案。

假设customer 表中的*AddressId 列可以是外键,那么您应该在Customer Hibernate 映射/类中将关系映射为many-to-one。 (请注意,Java 类应以大写字母开头。)

Customer 类中:

//each of these with getters/setters
Address officeAddress;
Address homeAddress;
Address secondaryAddress;

Customer.hbm.xml 文件中:

<many-to-one name="officeAddress" class="[package.name.]Address" column="officeAddressId"/>
<many-to-one name="homeAddress" class="[package.name.]Address" column="homeAddressId"/>
<many-to-one name="secondaryAddress" class="[package.name.]Address" column="secondaryAddressId"/>

然后,创建/保存这些对象的显式方法(可能在 DAO 方法中)是访问 Hibernate Session(通过 SessionFactory),创建/保存 Address 对象,将它们设置为Customer 对象,然后保存它。像这样的:

//in DAO create logic
Session session = sessionFactory.getCurrentSession(); //or openSession()
Address office = new Address();
Address home = new Address();
Address secondary = new Address();
//populate Address objects...
session.saveOrUpdate(office);
session.saveOrUpdate(home);
session.saveOrUpdate(secondary);
Customer customer = new Customer();
//populate Customer object...
customer.setOfficeAddress(office);
customer.setHomeAddress(home);
customer.setSecondaryAddress(secondary);
session.saveOrUpdate(customer);

如果您需要更新Customer引用的Address实体,然后get对象,再次设置正确的Address对象,并保存Customer

//in DAO update logic
Session session = sessionFactory.getCurrentSession(); //or openSession()
Customer customer = (Customer) session.get(Customer.class, customerId);
Address address = (Address) session.get(Address.class, addressId);
customer.setOfficeAddress(address);
session.saveOrUpdate(customer); //updates officeAddressId column to value of addressId

相当冗长,但明确而直接。

【讨论】:

  • 首先,感谢您的详细帮助。一个问题-->这是否意味着在使用 Hibernate 时我总是必须求助于对象组合?
  • 您不必这样做。您仍然可以将 FK 列映射为字符串或原始 property(而不是 many-to-one),但这样做将不允许您利用 Hibernate 进行自动关系查找或验证。每次获取 Customer 实体时,您都必须进行自己的 Address 检索。但是如果你用Addresses 编写Customer,Hibernate 会为你获取它们。所以这取决于你想做什么。
【解决方案2】:

首先,将客户类别的名称更改为 Customer。那么:

public Class Customer implements Serializable {
    ...

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "office_address_id")
    private Address officeAddress;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "home_address_id")
    private Address homeAddress;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "secondary_address_id")
    private Address secondaryAddress;

    ...
}

public Class Address implements Serializable {
    ...

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "officeAddress")
    private Set<Customer> officeCustomers = new HashSet<Customer>(0);

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "homeAddress")
    private Set<Customer> homeCustomers = new HashSet<Customer>(0);

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "secondaryAddress")
    private Set<Customer> secondaryCustomers = new HashSet<Customer>(0);

    ...
}

当然,您可以在 Address 类中为所有客户创建 getter。

【讨论】:

  • 组合必须和hibernate一起使用吗?我们不能只使用 Id 字段吗?
猜你喜欢
  • 2020-06-25
  • 2012-11-23
  • 1970-01-01
  • 2020-01-16
  • 2012-02-08
  • 1970-01-01
  • 2021-12-12
  • 2013-06-23
  • 1970-01-01
相关资源
最近更新 更多