Hibernate : How override an attribute from mapped super class
Asked Answered
B

2

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?

Bedford answered 10/3, 2011 at 9:51 Comment(1)
opensource.atlassian.com/projects/hibernate/browse/HHH-4380Telespectroscope
Z
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;}
}
Zulmazulu answered 10/3, 2011 at 10:5 Comment(9)
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()Bedford
@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.Zulmazulu
And how can I specify a sequence by table/entity for the id?Bedford
@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.Zulmazulu
@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.Zulmazulu
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); }Tabbitha
The answer here -- #8590428 provides what I consider to be a slightly better approach since it duplicates less code.Paulin
Wouldn't overriding the getter, getId(), not be possible? id is private in the GenericEntity, so the child has no access to the property.Pelion
@user2360507: Fixed. Thanks. That's there in the original post, and I copied that here, I think.Zulmazulu
E
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.

Eddins answered 10/3, 2011 at 10:1 Comment(3)
And how can I specify a sequence by table/entity for the id?Bedford
It will be great if you can post the source code of the class OurTableGeneratorWellspoken
@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.Eddins

© 2022 - 2024 — McMap. All rights reserved.