Gordon
Gordon

Reputation: 1210

@Entity not recognizing the @Id in a @MappedSuperclass

I'm attempting to create a base class for a set of entities to reduce coding effort and duplication. My thought is that the base class has the common meta-data fields, and the child classes deal with their unique attributes.

My base class:

@MappedSuperclass
public abstract class FinanceEntityBean {
    protected Long id;

    @Version
    private long version;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public Long getId() {
        return id;
    }

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

The first entity:

@Entity
@Table(name = "tag")
public class Tag extends FinanceEntityBean {
}

I've written tests using this code to do CRUD functions on the Tag entity, and they are all working fine.

My question is - why does Eclipse (Indigo) insist that Tag has an error:

The entity has no primary key attribute defined

I've changed that to a warning for now so my code will compile, but I'm curious why Eclipse isn't happy, and if I've misunderstood something.

Is this valid JPA 2.0 code? Hibernate 4.1.5 is my JPA provider.

Upvotes: 17

Views: 21213

Answers (6)

Shobhit Mittal
Shobhit Mittal

Reputation: 21

To anyone else facing this issue, ensure that the @Id you are importing is from the jakarta.persistence and not from the org.springframework.data.annotation package.

It happened with me, and had to spent considerable amount of time trying to find out what the real issue was.

Upvotes: 0

Raymond Naseef
Raymond Naseef

Reputation: 171

I know this is late, but it is still an issue. Thank you @Kemoda stating in a comment to the question, this can be turned off in Eclipse preferences.

Easiest way to "correct" this is to go set preference as you see fit for your environment. I like "Warning" because in cases where the entity does not have a primary key is an error situation.

JPA Errors/Warnings Type Entity has no primary key: [Error|Warning|Info|Ignore]

Upvotes: 1

Bryan Pugh
Bryan Pugh

Reputation: 123

I had the same problem, but for a different reason, but I didn't realize it. In further research I found that in my case I had the MappedSuperclass in a different jar. According to User Gas https://stackoverflow.com/users/3701228/gas:

"According to JPA spec, if you have jpa classes in separate jar you should add it to the persistence.xml (I don't know, if Hibernate requires that, but you can give it a try). Try to add following entry to your persistence.xml entity.jar"

He references what is the right path to refer a jar file in jpa persistence.xml in a web app? as a description on how to do this.

Upvotes: 2

Karen Butzke
Karen Butzke

Reputation: 1442

When using mixed access you have to specify the access type. See Eclipse Dali bug 323527 for giving a better validation error when both fields and properties are annotated.

Option 1 : Annotate the getVersion() method instead, only properties are annotated.
Option 2 : Specify mixed access type as follows:

@MappedSuperclass
@Access(AccessType.PROPERTY)
public abstract class FinanceEntityBean {
    protected Long id;

    @Version
    @Access(AccessType.FIELD)
    private long version;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public Long getId() {
        return id;
    }

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

Upvotes: 9

Brian Vosburgh
Brian Vosburgh

Reputation: 3276

If FinanceEntityBean is defined in a different Eclipse project from Tag, you may be suffering from the Dali bug "No primary key attribute in other plug-in project".

The workaround is to list FinanceEntityBean in the persistence.xml file associated with Tag.

Upvotes: 7

calvinkrishy
calvinkrishy

Reputation: 3928

I am fairly certain those are valid mappings.

The JPA 2.0 spec provides this example when talking about MappedSuperClasses (section 2.11.2):

@MappedSuperclass 
public class Employee {
    @Id protected Integer empId; 
    @Version protected Integer version; 
    @ManyToOne @JoinColumn(name="ADDR") protected Address address;
    public Integer getEmpId() { ... } 
    public void setEmpId(Integer id) { ... } 
    public Address getAddress() { ... } 
    public void setAddress(Address addr) { ... }
}

// Default table is FTEMPLOYEE table 
@Entity public class FTEmployee extends Employee {
    // Inherited empId field mapped to FTEMPLOYEE.EMPID 
    // Inherited version field mapped to FTEMPLOYEE.VERSION 
    // Inherited address field mapped to FTEMPLOYEE.ADDR fk
    // Defaults to FTEMPLOYEE.SALARY protected Integer salary;
    public FTEmployee() {}
    public Integer getSalary() { ... } 
    public void setSalary(Integer salary) { ... }
}

Upvotes: 3

Related Questions