views:

503

answers:

1

I have a legacy schema that cannot be changed. I am using a base class for the common features and it contains an embedded object. There is a field that is normally mapped in the embedded object that needs to be in the persistence id for only one (of many) subclasses. I have made a new id class that includes it but then I get the error that the field is mapped twice. Here is some example code that is much simplified to maintain the sanity of the reader:

@MappedSuperclass
class BaseClass {
    @Embedded
    private Data data;
}

@Entity
class SubClass extends BaseClass {
    @EmbeddedId
    private SubClassId id;
}

@Embeddable
class Data {
    private int location;

    private String name;
}

@Embeddable
class SubClassId {
    private int thingy;

    private int location;
}

I have tried @AttributeOverride but I can only get it to rename the field. I have tried to set it to updatable = false, insertable = false but this did not seem to work when used in the @AttributeOverride annotation. See answer below for the solution to this issue.

I realise I could change the base class but I really do not want to split up the embedded object to separate the shared field as it would make the surrounding code more complex and require some ugly wrapping code. I could also redesign the whole system for this corner case but I would really rather not.

I am using Hibernate as my JPA provider.

+1  A: 

I have found reason AttributeOverride was not working. When annotating the class you have to include the identifier of the embedded object in the name field. I was doing this:

@Entity
@AttributeOverride(name = "location", column = @Column(name = "location", insertable = false, updatable = false)
class SubClass extends BaseClass {

When it needed to be this:

@Entity
@AttributeOverride(name = "data.location", column = @Column(name = "location", insertable = false, updatable = false)
class SubClass extends BaseClass {

Strange thing is that changing the @Column's name field did work with the first version but the insertable and updatable fields were ignored. I do not know if that is a bug or a subtlety of the JPA spec.

Anyway, this does solve how to make the field read-only but it does not answer the original question: Is it possible to make a field from a mapped superclass transient?

Russ Hayward