2014-12-12 5 views
0

У меня есть два объекта в моем Java EAR: пользователь и пароль. Разумеется, в базе данных есть соответствующие таблицы: пользователи и пароли. Таблица паролей содержит идентификатор пользователя как внешний ключ. Итак, мой вопрос: как я могу извлечь запись пароля из таблицы паролей, когда Пользователь создан из таблицы «Пользователи», используя чисто аннотации? Я в недоумении.Ссылка на объект от другого объекта

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

ГККП:

@Entity 
@Table(name = "USERS") 
public class User{ 
    @Id 
    @Basic(optional = false) 
    @NotNull 
    @Column(name = "IDENTIFIER", nullable = false) 
     private Long identifier; 

    @JoinColumn(name = "UserIdentifier") 
    @OneToOne 
    private Password password; 

    // getters, setters, and other User related information such as username 
} 

@Entity 
@Table(name = "PASSWORDS") 
public class Password{ 
    @Id 
    @Basic(optional = false) 
    @NotNull 
    @Column(name = "IDENTIFIER", nullable = false) 
     private Long identifier; 

    @JoinColumn(name = "USERIDENTIFIER", referencedColumnName = "IDENTIFIER", nullable = false) 
    @OneToOne(optional = false, fetch = FetchType.EAGER) 
     private User useridentifier; 
    //getters, setters, and other password related fields such as the password it's self 
} 

ответ

0

Оказывается, ответ был достаточно прост. У меня были правильные аннотации, но мне нужно было несколько дополнительных вещей. Ниже приведен соответствующий код для обоих объектов.

@Entity 
@Table(name = "USERS") 
public class User{ 
    @Id 
    @Basic(optional = false) 
    @NotNull 
    @Column(name = "IDENTIFIER", nullable = false) 
     private Long identifier; 

    @JoinColumn(referencedColumnName = "PASSWORDS.USERIDENTIFIER", name="USERS.IDENTIFIER") 
    @OneToOne 
    private Password password; 

    // getters, setters, and other User related information such as username 
} 

@Entity 
@Table(name = "PASSWORDS") 
public class Password{ 
    @Id 
    @Basic(optional = false) 
    @NotNull 
    @Column(name = "IDENTIFIER", nullable = false) 
     private Long identifier; 

    @JoinColumn(name = "USERIDENTIFIER", referencedColumnName = "IDENTIFIER", nullable = false) 
    @OneToOne(optional = false, fetch = FetchType.EAGER) 
     private User useridentifier; 
    //getters, setters, and other password related fields such as the password it's self 
} 

Так что для будущих накопителей, которые имеют один объект, который ссылается на другой объект, вы должны указать имя и referencedColumnName аннотации JoinColumn, чтобы получить контейнер, чтобы тянуть в соответствующей сущности. Сделав это, я смог вывести правильную строку пароля из базы данных. Обратите внимание, что аннотация joincolumn в пользовательском объекте также должна иметь имя таблицы и что у той же аннотации в сущности пароля НЕ должны быть имена таблиц. Это не сработает иначе - поверьте, я попробовал и получил ошибку StackOverflow.

+2

и тот факт, что вам не хватает «mappedBy» для вашего 1-1 двунаправленного отношения. –

+0

Включает ли аннотацию mappedBy оба объекта или только базовый объект (Пользователь в этом случае)? или я полностью от основания? lol –

+0

@ neil-stockton Да, я пропустил это. Теперь редактируем его. –

0

Классы сущностей просто установить данные и отношения. Вы извлекаете данные из определенного экземпляра в своей бизнес-логике. Вы установили отношения с аннотациями @OneToOne в свойствах пользователя и пароля. То, что вам не хватает, является постоянным полем для объекта Password.

@Entity 
@Table(name = "PASSWORDS") 
public class Password{ 
    @Id 
    @Basic(optional = false) 
    @NotNull 
    @Column(name = "IDENTIFIER", nullable = false) 
    private Long identifier; 

    @JoinColumn(name = "USERIDENTIFIER", referencedColumnName = "IDENTIFIER", nullable = false) 
    @OneToOne(mappedBy = "password", optional = false, fetch = FetchType.EAGER) 
    private User useridentifier; 

    @NotNull 
    private String passwordValue; 

    // getters/setters go here, since your annotated fields are private 
} 

Затем вы можете пересечь отношения, извлекая экземпляр пользователя и перемещаясь в поле отношений. Таким образом, ваш бизнес-логика может выглядеть примерно так:

@PersistenceContext 
EntityManager em; 

Long userIdInput = ...; 
String passwordInput = ...; 

User user = em.find(User.class, userIdInput); 
// compare the input password with the stored password 
// retrieve the Password instance by navigating to the relationship field 
if (passwordInput.equals(user.getPassword().getPasswordValue()) { 
    // passwords match 
} else { 
    // passwords don't match 
} 

Вы получили имена пользователей до тех пор, котоpые ... странно. И вам, вероятно, следует взглянуть на то, как безопасно обрабатывать хранение значений пароля в вашей базе данных, так как не рекомендуется хранить их незашифрованные. Но это суть JPA.

Редактировать: владелец отношений должен быть установлен с использованием сопоставления, как указано @ neil-stockton.

+0

Я получаю это - я могу использовать некоторую логику, чтобы захватить пароль после того, как пользователь был найден; но я бы предпочел избежать этого и позволить контейнеру управлять вводом пароля пользователя из базы данных. Реализация этой логики потребует от меня выхода за пределы объекта и использования контроллера JPA. Так может ли контейнер автоматически заполнить поле пароля пользователя? Сущность пароля содержит строку пароля, но я опустил ее для краткого примера. Имя пользователя, также опущенное, является строкой; длинные значения, которые вы видите, являются идентификаторами каждой строки в таблицах. –

+0

Контейнер автоматически заполняет User.password после того, как он извлекает экземпляр пользователя в операции поиска или запроса, но в этом случае это другой объект. Вам все равно нужно найти объект и переместить поля отношений. Например, вы можете написать запрос JPQL для получения объекта Password для данного идентификатора пользователя. Но вы, похоже, хотите добавить всю логику в класс сущностей, что не работает JPA. Вы моделируете данные с помощью сущностей, а затем используете операции EntityManager для управления объектами. –

+0

Ну, это было не в то время, когда я разместил это. Но теперь я получил ответ. Я не хочу никакой логики в сущности. Я хочу, чтобы сущности обрабатывали свои собственные отношения, поэтому я могу сосредоточиться на бизнес-логике в своих сессионных компонентах. –