24

The generic entity, super class:

@MappedSuperclass
public abstract class GenericEntity {
    private Integer id;
    public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
}

The pojo:

@Entity
@Table(name = "POJO_ONE")
@SequenceGenerator(name = "HB_SEQ_POJO_ONE", sequenceName = "SEQ_POJO_ONE", allocationSize = 1)
public class PojoOne extends GenericEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HB_SEQ_POJO_ONE")
    @Column(name = "ID")
    @AttributeOverride(name = "id", column = @Column(name = "ID"))
    private Integer id;

    @Override
    public Integer getId() {return id;}
}

I try to use thoses annotations : @AttributeOverride, @Id, ... but It doesn't work. Can you help me? I want to override the attribute "id" to specify another column name and a sequence by pojo/table. What is the best way to do that?

BasicCoder
  • 1,661
  • 10
  • 27
  • 42

2 Answers2

36

Try this, instead

@MappedSuperclass
public abstract class GenericEntity {
    protected Integer id;
    ...

    public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
}


@Entity
@Table(name = "POJO_ONE")
@SequenceGenerator(name = "HB_SEQ_POJO_ONE", sequenceName = "SEQ_POJO_ONE", allocationSize = 1)
@AttributeOverride(name = "id", column = @Column(name = "ID"))
public class PojoOne extends GenericEntity {
    // we should not define id here again
    ...

    @Override
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HB_SEQ_POJO_ONE")
    public Integer getId() {return id;}
}
Adeel Ansari
  • 39,541
  • 12
  • 93
  • 133
  • With this solution, when I try to save, I have this exception : `org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save()` – BasicCoder Mar 10 '11 at 12:29
  • @user616564: Then just take the `@GeneratedValue` annotation to the `MappedSuperClass`, but then subclasses wouldn't be able to give their own implementation. If that is fine with you. – Adeel Ansari Mar 10 '11 at 12:36
  • And how can I specify a sequence by table/entity for the id? – BasicCoder Mar 10 '11 at 12:51
  • @user616564: I meant both of those. But, of course, it would then kill the purpose and allow you to just use the different column name. I'm afraid, you may not want this. – Adeel Ansari Mar 10 '11 at 14:52
  • @user616564: I just changed my code, to bring the `@Id` to the subclass. Is this version working? If it is, then your subclasses must use `@Id` annotation. – Adeel Ansari Mar 10 '11 at 15:03
  • The version of @AdeelAnsari works fine, but if your super class is abstract, it imho works even easier when you just have abstract setters and getters in the superclass, this way you can define the field in the subclass. // superclass public abstract class GenericEntity { public abstract Long getId(); public abstract void setId(Long id); } – mkraemerx Mar 16 '13 at 23:16
  • 2
    The answer here -- http://stackoverflow.com/questions/8589928/mappedsuperclass-change-sequencegenerator-in-subclass provides what I consider to be a slightly better approach since it duplicates less code. – sfitts Jun 13 '14 at 21:34
  • 1
    Wouldn't overriding the getter, getId(), not be possible? id is private in the GenericEntity, so the child has no access to the property. – user2360507 Nov 02 '20 at 02:13
  • 1
    @user2360507: Fixed. Thanks. That's there in the original post, and I copied that here, I think. – Adeel Ansari Nov 02 '20 at 03:39
4

Why don't you annotate the id of GenericEntity with @Id? You also should not redefine id but put the @AttributeOverride(name = "id", column = @Column(name = "ID")) on the class rather than a field.

Edit:

We're using this in our base class (package.OurTableGenerator is our own implementation):

@GeneratedValue ( generator = "ourTableGenerator", strategy = GenerationType.TABLE )
@GenericGenerator ( name = "ourTableGenerator", strategy = "package.OurTableGenerator",
  parameters = { @Parameter ( name = OurTableGenerator.TABLE_PARAM, value = "t_sequence" ),
                 @Parameter ( name = OurTableGenerator.SEGMENT_COLUMN_PARAM, value = "c_entity" ),
                 @Parameter ( name = OurTableGenerator.VALUE_COLUMN_PARAM, value = "c_nextHi" ),
                 @Parameter ( name = OurTableGenerator.INCREMENT_SIZE_COLUMN_PARAM, value = "c_blocksize" ) } )
@Id
@Column(name = "c_uid")
private Long uid;

This let's us specify a differenc block size and sequence per entity/table.

For your own table generator you could subclass org.hibernate.id.TableGenerator.

Thomas
  • 87,414
  • 12
  • 119
  • 157
  • And how can I specify a sequence by table/entity for the id? – BasicCoder Mar 10 '11 at 13:12
  • It will be great if you can post the source code of the class OurTableGenerator – Kiran Kumar Mar 30 '17 at 08:01
  • @KiranKumar the exact code depends on the Hibernate version but basically it's a subclass of `org.hibernate.id.enhanced.TableGenerator` and a few overridden methods, especially `configure(...)`, `generate(...)` as well as the methods that provide the SQL strings. – Thomas Mar 30 '17 at 14:09