sferrazjr
sferrazjr

Reputation: 315

Hibernate: mapping same column for two different classes

I'm working on a legacy system, that doesn't have a proper unit test, neither a any so I need to be very careful about any change that I do in the system.

The basic scenario that I have is: I got a Person that has a ManyToOne relationship with Address, I can't change this relationship. But know there are types of Address, for instance: billing address and post address.

public class Person {

@Id
@Column(name = "PERSON_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

@Column(name = "PERSON_NAME")
private String personName;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ADDRESS_ID")
private Address address;

getters and setters

address class

public class Address {

private static final long serialVersionUID = 1L;

@Id
@Column(name = "ADDRESS_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(name = "STREET_1_NAME")
private String street1Name;

@Column(name = "STREET_2_NAME")
private String street2Name;

getters and setters

I'm thinking to add the column ADDRESS_TYPE to ADDRESS table, but I'm struggling on how to implement it. I just want to have a new attribute postalAddress of type Address and get the postalAddress as easy as just getPostalAddress.

Upvotes: 2

Views: 4598

Answers (3)

sferrazjr
sferrazjr

Reputation: 315

Thanks Alan, your suggestion helped but I end up using InheritanceType because of compatibility with legacy code.

My Address class now looks like:

@Entity
@Table(name = "ADDRESS")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name="ADDRESS_TYPE",
    discriminatorType=DiscriminatorType.INTEGER
)
@DiscriminatorValue("null")

public class Address  {

My PostalAddress looks like:

@Entity
@Table(name = "ADDRESS")
@DiscriminatorValue(value="2")
public class PostalAddress extends Address {

    private static final long serialVersionUID = 1L;

    @ManyToOne
    @JoinColumn(name = "INSURED_ID")
    private Insured insured;

    public void setInsured(Insured insured) {
        this.insured = insured;
    }

    public Insured getInsured() {
        return insured;
    }

}

So, for those addresses inserted in the past without a type I'm assuming null and for compatibility the new ones will be 'null' as well, just the PostalAddress will be '2'.

And my Person class looks like

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ADDRESS_ID")
private Address address;

@Transient
private PostalAddress postalAddress;

I know it sounds odd, but I've been asked to have a relationship Person 1 - N PostalAddress.

Upvotes: 2

Alan Hay
Alan Hay

Reputation: 23246

Further to my previous comment sounds to me like you want a one-to-many from Person to Address using a Map.

Add the address_type column as you suggested and create an Enum AddressType (POSTAL, BILLING):

In Person:

//there are various MapKey annotations however, without testing I think these are what you need
@OneToMany
@MapKeyEnumerated(EnumType.String) //tells Hibernate we want the type to contain BILLING/POSTAL etc rather than the ENUM ordinals (0,1 etc)
@MapKeyColumn(name ="address_type")
private Map<AddressType, Address) addresses;

public Address getPostalAddress(){
return addresses.get(AddressType.POSTAL);
}

public Address getBillingAddress(){
return addresses.get(AddressType.Billing);
}

//or even
public Address getAddress(AddressType type){
return addresses.get(type);
}
  • I am assuming that the addresses table has a FK to persons.

Upvotes: 0

Eugen Halca
Eugen Halca

Reputation: 1785

hust add :

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "POSTAL_ADDRESS_ID")
private Address postalAddress;

this will add a new column to your Person table managing the relation. No need to add ADDRESS_TYPE to ADDRESS table since it will be redundant.

Upvotes: 0

Related Questions