0

Suppose i want to have a composite key as street, city for purchase order entity.

Below is how i identify doing it,

    @Embeddable
    public class BillingAddress implements Serializable {

        private String street;
        private String city;

        public BillingAddress(){

        }

        public BillingAddress(String street, String city) {
            this.street = street;
            this.city = city;
        }
        //with getters and setters
}



@Entity
@IdClass(BillingAddress.class)
public class PurchaseOrder {

    public PurchaseOrder(BillingAddress billingAddress) {
        street = billingAddress.getStreet();
        city = billingAddress.getCity();

    }

    @Id
    @AttributeOverrides({
            @AttributeOverride(name = "street", column = @Column(name = "STREET")),
            @AttributeOverride(name = "city", column = @Column(name = "CITY")) })
    private String street;
    private String city;
    private String itemName;

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

}

I want to understand what is really @AttributeOverrides annotation do? Even i change to colomn name to something STREET1 i still see the table created with column name STREET. So what is column = @Column(name = "STREET")) doing here.

Also instead of constructore taking the BillingAddress i can have it like a field of PurchaseOrder class right like,

 public class PurchaseOrder {
     BillingAddress billingAddress;

}

In this case how this going to change? Do i still need to have private String street; private String city; in PurchaseOrder?

Finally i read that using composite keys should be avoided in new data base system design which using composite primary key is applicable a situation where in order to map the legacy data base tables with out changing the data base table structure right? Is that statement a valid one?

//Edit question

Saving purchase order which billing address is in the field,

PurchaseOrder purchaseOrder = new PurchaseOrder();
purchaseOrder.setItemName("name");

BillingAddress billingAddress = new BillingAddress();
billingAddress.setCity("c1"); billingAddress.setStreet("s1");                                                              purchaseOrder.setBillingAddress(billingAddress); 
session.save(purchaseOrder);
FrankD
  • 859
  • 4
  • 19
  • 31

2 Answers2

1

There's are few question you asked, I tried to go through all of them and answer each one:

What does @AnnotationOverride do?

answer here: What does @AttributeOverride mean?

The second question is a bit unclear to me but I presume you're asking whether you have to include all the fields from the composite key in the PurchaseOrder class.

No, I don't think so. Here's an example I've put together real fast:

@Entity
@Table(name = "PURCHASE_ORDER")
public class PurchaseOrder{

    @Id
    private BillingAddress billingAddress;

    //getters & setters

    @Embeddable
    public static class BillingAddress implements Serializable {
        @Column(name = "street")
        private String street;
        @Column(name = "city")
        private String city;
        @Column(name = "itemName")
        private String itemName;

        //getters & setters

    }
}

Don't worry about the syntax, just the structure. You can even add extra field into PurchaseOrder which isn't an id.

Should I use composite keys or not?

answer here: Should I use composite primary keys or not?

Community
  • 1
  • 1
Lenymm
  • 879
  • 1
  • 6
  • 27
0

Well, your PurchaseOrder class does not extend from a mapped entity of any kind, and neither do the properties that you are (currently) applying the @AttributeOverrides to. So, there is nothing to actually override and your JPA provider is simply ignoring the annotations. What I think you are trying to do is define an embedded id for an entity, while overriding some of the column mappings for that id. You can do this with some modifications to your current code:

@Entity
public class PurchaseOrder {
    @EmbeddedId
    @AttributeOverrides({
            @AttributeOverride(name = "street", column = @Column(name = "BILLING_STREET")),
            @AttributeOverride(name = "city", column = @Column(name = "BILLING_CITY")) })
    private BillingAddress billingAddress;

    private String itemName;

    // Constructors, Getters/Setters
}

Note that I've changed the names of the overridden attributes, since with your current example, the embedded id name and overridden names are the same.

Perception
  • 79,279
  • 19
  • 185
  • 195
  • i have gone with below article which auther mentioned about street and city fields in PurchaseOrder entity as , " The duplicate code is, of course, the two private data members for street and city. This duplication is required to create the composite key." http://www.ibm.com/developerworks/library/os-hibernatejpa/ – FrankD Jan 03 '13 at 03:41
  • Also what if the relationship between PurhaseOrder and BillingAddress in composition where PuchaseOrder can not exsist with out a billing address.(If you remove the billing address purchase order should be deleted kinf of scenario) In that case i need to passe the billing address to the purchase order constructor right instead of having it as a field as you showed in your code? – FrankD Jan 03 '13 at 03:43
  • That tutorial appears to have a mistake in it - when using @IdClass you need to map all the elements of the composite key in the owning entity. To your second question, the JPA framework validates entities before saving them - this includes verifying the embedded id is set. – Perception Jan 03 '13 at 03:54
  • i removed billing address from the constructor and make it as your one but it gives a exception, "Initial SessionFactory creation failed.org.hibernate.AnnotationException: Property of @IdClass not found in entity hello.domain.PurchaseOrder: city Exception in thread "main" java.lang.ExceptionInInitializerError" – FrankD Jan 05 '13 at 01:35
  • the i just put the fields street and city to the PurchaseOrder class and that exception and PuchaseOrder table created with composite primary key. But when saving purchase order it gives me below exception,ERROR: Column 'city' cannot be null. Please see the edit question section to see how i save purchase order this time. – FrankD Jan 05 '13 at 01:53
  • Add setters/getter for the billing address to your purchase order class. And then after initializing the billing address, set it - `purchaseOrder.setBillingAddress(billingAddress)`. – Perception Jan 05 '13 at 02:08