javaspringhibernatejpa

How can we make @TenantId as part of composite primary key in spring boot jpa


I have a multi tenants LMS application. I have Academy entity which will act as tenant in my LMS. Every other entity will have academy_id column.

Using discriminator based multi tenancy feature of hibernate.

@Entity
@Data
public class Academy implements Serializable {
  @Id private long id;

  @Column(nullable = false)
  private String name;

  @Column(nullable = false, unique = true)
  private String domain;

  @Column(nullable = false)
  private boolean isActive;

  @Column(nullable = false)
  private long features;

  @Column(nullable = false, updatable = false)
  private ZonedDateTime createdAt;

  @Column(nullable = false)
  @Version
  private ZonedDateTime lastModified;

  @PrePersist
  protected void setCreatedAt() {
    createdAt = ZonedDateTime.now();
  }
}

I have another entity, AcademyUser.

@Entity
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = {"academy_id", "email"})})
public class AcademyUser extends EntityBase {
  @EmbeddedId private AcademyUserKey key;

  @Column(nullable = false)
  @Enumerated(EnumType.STRING)
  private UserType userType;

  private PhoneNumber phoneNumber;

  @Column(nullable = false)
  private String firstName;

  @Column(nullable = false)
  private String lastName;

  @Column(nullable = false)
  private boolean isBlocked;

  @Column(nullable = false)
  private short roles;
}


// AcademyUserKey.java
@Data
@Builder
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class AcademyUserKey implements Serializable {
  @TenantId
  @Column(name = "academy_id") // Map to your database column
  private long academyId;

  @Column(name = "user_email")
  private String email;
}

I am getting the following error

Failed to initialize JPA EntityManagerFactory: Property 'org.w3worker.academy.api_server.academy_user.models.AcademyUser.key.academy' is annotated 'interface org.hibernate.annotations.TenantId' which is not an '@IdGeneratorType'

In sort, unable to use @TenantId as part of the primary key. Is there any solution?


Solution

  • Do NOT map relationships inside @Embeddable classes. (Only primitive types are allowed there.)

    To use tenantId as a part of the primary key, update the code as below.

    @Data
    @Builder
    @Embeddable
    @NoArgsConstructor
    @AllArgsConstructor
    public class AcademyUserKey implements Serializable {
      
      @Column(name = "academy_id")
      private long academyId;
    
      @Column(name = "user_email")
      private String email;
    }
    
    
    @Entity
    @Data
    @SuperBuilder
    @NoArgsConstructor
    @AllArgsConstructor
    @Table(uniqueConstraints = {@UniqueConstraint(columnNames = {"academy_id", "email"})})
    public class AcademyUser extends EntityBase {
      
      @EmbeddedId 
      private AcademyUserKey key;
    
      @ManyToOne
      @MapsId("academyId")
      @JoinColumn(name = "academy_id")
      private Academy academy;
        
      ...
    }