Hibernate : How override an attribute from mapped super class

55,750

Solution 1

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;}
}

Solution 2

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.

Share:
55,750
BasicCoder
Author by

BasicCoder

Updated on November 02, 2020

Comments

  • BasicCoder
    BasicCoder over 3 years

    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
    BasicCoder over 13 years
    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()
  • Adeel Ansari
    Adeel Ansari over 13 years
    @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.
  • BasicCoder
    BasicCoder over 13 years
    And how can I specify a sequence by table/entity for the id?
  • BasicCoder
    BasicCoder over 13 years
    And how can I specify a sequence by table/entity for the id?
  • Adeel Ansari
    Adeel Ansari over 13 years
    @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
    Adeel Ansari over 13 years
    @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.
  • mkraemerx
    mkraemerx over 11 years
    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); }
  • sfitts
    sfitts about 10 years
    The answer here -- stackoverflow.com/questions/8589928/… provides what I consider to be a slightly better approach since it duplicates less code.
  • Kiran Kumar
    Kiran Kumar about 7 years
    It will be great if you can post the source code of the class OurTableGenerator
  • Thomas
    Thomas about 7 years
    @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.
  • user2360507
    user2360507 over 3 years
    Wouldn't overriding the getter, getId(), not be possible? id is private in the GenericEntity, so the child has no access to the property.
  • Adeel Ansari
    Adeel Ansari over 3 years
    @user2360507: Fixed. Thanks. That's there in the original post, and I copied that here, I think.