views:

869

answers:

3

Is it possible to create a table (from a JPA annotated hibernate entity) that does not contain a primary key / Id?

(I know this is not a good idea. A table should have a primay key.)

A: 

If it looks like a fish, swims in water, eats fish food and smells like a fish is more than likely is a fish. Re-architect you app and use a primary key properly.

ps. Hibernate, JPA requires each entity to have an ID (primary key)

Karl
ever heard of legacy systems?
Schildmeijer
Agree w/Rodger. This is useful for using legacy systems that you often are not allowed to re-architect, nor would you want to due to risk.
awied
Have heard that ibatis is better for this situation where you have a funny legacy system. Alternative is to use views
Karl
+2  A: 

I found that its not possible to do so. So bad luck for those working with legacy systems. If you reverse engineer (create jpa annotated entities from existing jdbc connection) the table will create two java classes, one Entity and with one field; id, and one embeddable id containg all the columns from your relation.

Schildmeijer
+1  A: 

Roger's self-answer is correct. To elaborate a bit on what is meant (I wasn't clear on it at first and figured this would help):

Say you have you have a table Foo as such:

TABLE Foo (
bar varchar(20),
bat varchar(20)
)

Normally, you can write a class w/Annotations to work with this table:

// Technically, for this example, the @Table and @Column annotations 
// are not needed, but don't hurt. Use them if your column names 
// are different than the variable names.

@Entity
@Table(name = "FOO")
class Foo {

  private String bar;
  private String bat;


  @Column(name = "bar")
  public String getBar() {
   return bar;    
  }

  public void setBar(String bar) {
   this.bar = bar;    
  }

  @Column(name = "bat")
  public String getBat() {
   return bat;    
  }

  public void setBat(String bat) {
   this.bat = bat;    
  }

}

.. But, darn. This table has nothing we can use as an id, and it's a legacy database that we use for [insert vital business function]. I don't think they'll let me start modifying tables in order for me to use hibernate.

You can, instead, split the object up into a hibernate-workable structure which allows the entire row to be used as the key. (Naturally, this assumes that the row is unique.)

Split the Foo object into two thusly:

@Entity
@Table(name = "FOO")
class Foo {

  @Id
  private FooKey id;

  public void setId(FooKey id) {
    this.id = id;
  }

  public void getId() {
    return id;
  }
}

and

@Embeddable
class FooKey implements Serializable {
  private String bar;
  private String bat;

  @Column(name = "bar")
  public String getBar() {
   return bar;    
  }

  public void setBar(String bar) {
   this.bar = bar;    
  }

  @Column(name = "bat")
  public String getBat() {
   return bat;    
  }

  public void setBat(String bat) {
   this.bat = bat;    
  }

}

.. And that should be it. Hibernate will use the Embeddable key for its required identity and you can make a call as normal:

Query fooQuery = getSession().createQuery("from Foo");

Hope this helps first-timers with getting this working.

awied