Hibernate наследование с другим первичным ключом

Я пытаюсь создать наследование со стратегией TABLE_PER_CLASS, но хочу иметь разные первичные ключи для каждой таблицы. Возможно ли это?

У меня есть один класс Register, который имеет миллионы экземпляров, некоторые из этих экземпляров являются «особыми» и имеют разные правила для своих столбцов и дополнительных столбцов.

@MappedSuperclass

public abstract class Register {


    @Id
    @Column(nullable = false, unique = true, updatable = false)
    private Long userId;


    private Date checked;

    @Column(nullable = false)
    private RegisterState tipo;
}


@Entity
@AttributeOverrides({ @AttributeOverride(name = "userId", column = @Column(nullable = false, unique = false, updatable = false)) })
public class PotencialRegister extends Register implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;


    @Column(length = 64, nullable = false, unique = false)
    private String referer;
}

Для базового регистра мне не нужен атрибут Id, потому что у меня есть один уникальный столбец, но для специализированного объекта этот столбец не уникален, поэтому я добавил дополнительный атрибут.

проблема в том, что hibernate использует родительский идентификатор для создания составного первичного ключа (сгенерированная схема):

create table PotencialRegister (
        id integer not null,
        userId bigint not null,
        checked datetime(6),
        tipo integer not null,
        referer varchar(64) not null,
        primary key (id, userId)
    )  

    create table Register (
        userId bigint not null,
        checked datetime(6),
        tipo integer not null,
        primary key (userId)
    )  

Столбцы правильные, и мне нужна схема, но я хотел бы удалить элемент «id» из первичного ключа PotencialRegister.


person Rafael Lima    schedule 07.11.2017    source источник
comment
Вы все еще видите какие-либо проблемы, указанные в ответе ниже?   -  person Ravik    schedule 24.11.2017


Ответы (3)


Вы можете создать другой класс, в котором нет столбца @Id, и использовать этот класс в качестве базового класса для каждого типа регистра.

поэтому ваш класс Register будет выглядеть так:

@MappedSuperclass

public abstract class Register {

    @Column(nullable = false, unique = true, updatable = false)
    private Long userId;

    private Date checked;

   @Column(nullable = false)
    private RegisterState tipo;
}

Теперь для обычного регистра вы можете сделать следующее:

 @Entity   
 public class NormalRegister extends Register implements Serializable{

    @Id
    public Long getUserId(){
      return super.userId;
    }

     public void setUserId(Long uId){
        super.userId=uId;
      }

   }

затем вы определяете свой класс PotencialRegister как:

@Entity
@AttributeOverrides({ @AttributeOverride(name = "userId", column = @Column(nullable = false, unique = false, updatable = false)) })
public class PotencialRegister extends Register implements Serializable {

    private Integer id;


    @Column(length = 64, nullable = false, unique = false)
    private String referer;

    @Id
    public Long getUserId(){
      return super.userId;
    }

     public void setUserId(Long uId){
        super.userId=uId;
      }

}

При этом у вас нет идентификатора в базовом классе, и все подклассы могут определять свой собственный атрибут идентификатора.

person Ravik    schedule 16.11.2017
comment
если вы найдете ответ полезным, пожалуйста, поделитесь баллами за вознаграждение. Если вам нужны дополнительные разъяснения, пожалуйста, спросите. - person Ravik; 17.11.2017
comment
На самом деле это не решает мою проблему, потому что я не хотел иметь столбец id... идеальный первичный ключ - это userId, если я поместил его в абстрактный класс, у меня возникла проблема, если я взлетаю, и поместите в каждый расширенный класс, я получаю несовместимости - person Rafael Lima; 18.11.2017
comment
Я понимаю, что ваша проблема связана с классом PotenicalRegister, где идентификатор вашей реализации и столбцы userId становятся частью первичного ключа, поскольку он наследуется от абстрактного класса. С моим решением вы можете определить первичный ключ так, как хотите, в абстрактном классе нет первичного ключа, и каждая реализация класса регистра может иметь свой первичный ключ pwn. - person Ravik; 18.11.2017
comment
Пожалуйста, дайте мне знать, какие несовместимости возникают при добавлении атрибута @Id в каждый расширенный класс, чтобы мы могли предоставить вам решение. - person Ravik; 20.11.2017
comment
Я получил исключение при удалении @Id из базового класса. Я не мог понять, что мне не хватает. Вы можете помочь? Ошибка создания bean-компонента с именем «registerRepository»: не удалось вызвать метод инициализации; вложенным исключением является java.lang.IllegalArgumentException: этот класс [....Register] не определяет IdClass - person Ming; 08.10.2018
comment
Я предполагаю, что вы не добавили @Id в расширенный класс, в этом случае Hibernate не сможет идентифицировать столбец Id для объекта. - person Ravik; 10.10.2018

В иерархии таблицы для каждого класса предполагается, что свойства Version и Id унаследованы от корневого класса. Если я не ошибаюсь, вы не можете использовать несколько атрибутов Id в одной иерархии классов/классов. В вашем случае в базовом классе вы можете поместить свойства, которые являются общими для таблиц, и использовать атрибут Id только в определенных классах (представляющих отдельные таблицы).

person Har Krishan    schedule 20.11.2017

вы не можете переопределить userId в качестве первичного ключа: https://hibernate.atlassian.net/browse/HHH-11771. Поэтому я считаю, что вам следует подумать о переносе userId из абстрактного класса в реализации с соответствующими аннотациями.

person Alexey Tatarikov    schedule 25.10.2019