Home > Blockchain >  How to map an abstract class without an id in Hibernate
How to map an abstract class without an id in Hibernate

Time:05-12

The background of this project is that there are two types of users, suscriber users and amdin users. There are also two types of sucriber users, students and professors. Admin users can register new classrooms, and suscriber users can suscribe to classrooms to see different information such as temperature etc.

The problem is that I have to map a ManyToMany bidirectional relationship between clasrooms and suscriber users and I'm getting the following error in the Classroom class:

'Many To Many' attribute value type should not be 'SuscriberUser'

and this exception:

org.hibernate.AnnotationException: Use of @OneToMany or @ManyToMany targeting an unmapped class

This is my code:

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class User implements IUser {
    private String name;

    // some other fields
    // constructors
    // getters and setters
}
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class SuscriberUser extends User implements ISuscriberUser {
    @ManyToMany(mappedBy = "suscribers")
    private ArrayList<Classroom> classroomSubscriptions;

    // constructors
    // getters and setters
}

For example one concrete class of SuscriberUser:

@Entity
@Table(name = "student")
public class Student extends SuscriberUser {
    @Id
    private int studentId;

        // constructors
        // getters and setters
}
@Entity
@Table(name = "classroom")
public class Classroom implements IClassroom {
    @Id
    private int internalId;

    // other fields

    @ManyToMany()
    @JoinTable(name = "suscribers")
    private ArrayList <SuscriberUser> suscribers;

    // constructors
    // getters and setters
}

I have also tried using @MappedSuperclass in both classes User and SuscriberUser, but it doesn't work. I guess it's because both abstract classes don't have an id.

How can I solve this?

CodePudding user response:

The User class is just a collector of fields, therefore it can become a @MappedSuperClass.

@MappedSuperClass
public abstract class User implements IUser {
    
    private String name;

    // some other fields
    // constructors
    // getters and setters
}

If you use @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS), you have a table per class, so you need to:

  1. remove abstract
  2. add @Entity annotation
  3. add @Table to define a name
  4. add @Id to the id column.
@Entity
@Table(name = "subscriber_user")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class SuscriberUser extends User implements ISuscriberUser {

    @Id
    private int id;
    
    @ManyToMany(mappedBy = "suscribers")
    private List<Classroom> classroomSubscriptions;

    // constructors
    // getters and setters
}

More info here.

The student class does not need an id column because is in the parent class.

@Entity
@Table(name = "student")
public class Student extends SuscriberUser {

        // constructors
        // getters and setters
}

Pay attention that the join table is another one. This table contains the relations between students and classrooms and it can be named subscription.

@Entity
@Table(name = "classroom")
public class Classroom implements IClassroom {
    @Id
    private int internalId;

    // other fields

    @ManyToMany
    @JoinTable(
        name = "subscription", 
        joinColumns = @JoinColumn(name = "internalId"), // id class room
        inverseJoinColumns = @JoinColumn(name = "id")) // id user
    private List<SuscriberUser> suscribers;

    // constructors
    // getters and setters
}
  • Related