#java #spring #hibernate #postgresql #jpa-2.1
#java #spring #спящий режим #postgresql #jpa-2.1
Вопрос:
Я пытаюсь создать одно-единственное отношение между пользователем и таблицей аутентификации. Проблема в том, что при создании таблицы DB «Auth» я не вижу внешнего ключа в таблице аутентификации, который должен ссылаться на Person. Цель состоит в том, чтобы таблица аутентификации использовала тот же первичный ключ таблицы Person.
@MappedSuperclass
public abstract class DomainBase {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Version
@Column(name="OPLOCK")
private Integer version;
}
@Entity
@Table(name = "person")
public class Person extends DomainBase {
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="auth_id")
private Auth auth;
}
@Entity
public class Auth {
@Id
@GeneratedValue(generator="foreign")
@GenericGenerator(name="foreign", strategy = "foreign", parameters={
@Parameter(name="property", value="person")
})
@Column(name="person_id")
private int personId;
---------------------------------
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private Person person;
}
Мои скрипты базы данных после генерации гибернации DB.
CREATE TABLE auth
(
person_id integer NOT NULL,
activate boolean,
activationid character varying(255),
last_login_attempt_date timestamp without time zone,
last_login_attempt_timezone character varying(255),
last_login_date timestamp without time zone,
last_login_timezone character varying(255),
nonlocked boolean,
num_login_attempts integer,
CONSTRAINT auth_pkey PRIMARY KEY (person_id),
CONSTRAINT uk_d68auh3xsosyrjw3vmwseawvt UNIQUE (activationid)
)
WITH (
OIDS=FALSE
);
ALTER TABLE auth
OWNER TO postgres;
Ответ №1:
Похоже, проблема в том, что вы дважды объявляете аннотацию @OneToOne между таблицей «person» и таблицей «auth», не указывая связь между ними. Взгляните на документацию hibernate, в пункте 2.2.5.1, есть несколько примеров использования взаимно однозначной ассоциации.
Для меня лучший способ — настроить ассоциацию в одной таблице, той, в которой объявлен столбец foreing key, и использовать mappedBy
параметр в другом объекте. В вашем коде это будет :
@Entity
@Table(name = "person")
public class Person extends DomainBase {
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="auth_id")
private Auth auth;
}
@Entity
public class Auth {
@Id
@GeneratedValue(generator="foreign")
@GenericGenerator(name="foreign", strategy = "foreign", parameters={
@Parameter(name="property", value="person")
})
@Column(name="person_id")
private int personId;
@OneToOne(mappedBy = "auth")
private Person person;
....
}
Это второй пример в документации hibernate, представленный сразу после предложения «В следующем примере связанные объекты связаны через явный столбец внешнего ключа». Я протестировал этот код, и появился столбец «auth_id».
Комментарии:
1. документация по гибернации отсутствует. Что превращает onetoone в общий первичный ключ? Из документов, которые вы показали, я не вижу, что заставляет это быть. Можете ли вы объяснить?
2. Под «общими первичными ключами» я просто подразумеваю использование идентификатора таблицы как внешнего ключа в другой таблице, чтобы разрешить связь между ними. Я не должен был использовать термин «общий». Я редактирую свой ответ
3. При такой конфигурации я получаю эту ошибку -> попытка присвоить идентификатор из нулевого свойства один-к-одному [XXXXX.domains.Auth.person] при попытке перейти по этой ссылке
4. Когда вы устанавливаете аутентификацию для пользователя, у аутентификации должен быть идентификатор. Чтобы реализовать это, создайте auth, сохраните его, получите и затем свяжите его с объектом person . В конкретных терминах добавьте
Auth authSaved = this.authRepository.save(auth)
между строкой 3 и строкой 4. Возможно, вам нужно изменить стратегию сгенерированного значения для идентификатора аутентификации. Если это так, используйте@GeneratedValue(strategy = GenerationType.AUTO)
вместо обоих@GeneratedValue
и@GenericGenerator
аннотаций, это должно работать.5. думал, что это было целью использования общего первичного ключа. Как и в случае, если владелец поделится своим сохраненным первичным ключом с зависимым, а взамен зависимый будет использовать это значение в качестве собственного первичного ключа.