Hibernate не получает полную информацию об объекте @ManyToOne, необходимую после выполнения обновления - PullRequest
1 голос
/ 13 июля 2020

У меня есть сценарий, когда мне нужно обновить отношение таблицы подробностей «USER_PROFILE» в этом случае и обновить ссылку на столбец отношения на родительскую таблицу «NATIONALITY» (просто изменение столбца NATIONALITY_ID в USER_PROFILE, а таблица NATIONALITY - это просто предопределенный поиск и не изменится).

Итак, мой пример кода выглядит следующим образом: -

@Entity
@Table(name = "USER_PROFILE", schema = "OQ_IDEATE")
public class UserProfile {

    private Long userProfileId;
    private Nationality nationalityByNationalityId;
    private List<UserSkills> userSkillsByUserProfileId;

    @Id
    @Column(name = "USER_PROFILE_ID", nullable = false)
    public Long getUserProfileId() {
        return userProfileId;
    }

    public void setUserProfileId(Long userProfileId) {
        this.userProfileId = userProfileId;
    }

    @ManyToOne
    @JoinColumn(name = "NATIONALITY_ID", referencedColumnName = "NATIONALITY_ID")
    public Nationality getNationalityByNationalityId() {
        return nationalityByNationalityId;
    }

    public void setNationalityByNationalityId(Nationality nationalityByNationalityId) {
        this.nationalityByNationalityId = nationalityByNationalityId;
    }

    @OneToMany(mappedBy = "userProfileByUserId", cascade = CascadeType.ALL)
    public List<UserSkills> getUserSkillsByUserProfileId() {
        return userSkillsByUserProfileId;
    }

    public void setUserSkillsByUserProfileId(List<UserSkills> userSkillsByUserProfileId) {
        this.userSkillsByUserProfileId = userSkillsByUserProfileId;
    }
}

@Entity
public class Nationality {
    private Long nationalityId;
    private String nationalityNameEn;

    public Nationality() {
    }

    public Nationality(Long nationalityId) {
        this.nationalityId = nationalityId;
    }

    @Id
    @Column(name = "NATIONALITY_ID", nullable = false)
    public Long getNationalityId() {
        return nationalityId;
    }

    public void setNationalityId(Long nationalityId) {
        this.nationalityId = nationalityId;
    }

    @Basic
    @Column(name = "NATIONALITY_EN", nullable = false, length = 200)
    public String getNationalityNameEn() {
        return nationalityNameEn;
    }

    public void setNationalityNameEn(String nationalityNameEn) {
        this.nationalityNameEn = nationalityNameEn;
    }

}
@Entity
@Table(name = "USER_SKILLS", schema = "OQ_IDEATE")
@IdClass(UserSkillsPK.class)
public class UserSkills {
    private Long userId;
    private Long skillId;
    private UserProfile userProfileByUserId;
    private Skill skillBySkillId;

    public UserSkills() {
    }

    public UserSkills(UserProfile userProfile, Skill skill){
        this.userProfileByUserId = userProfile;
        this.skillBySkillId = skill;
        this.userId = userProfile.getUserProfileId();
        this.skillId = skill.getSkillId();
    }

    @Id
    @Column(name = "USER_ID", nullable = false)
    public Long getUserId() {
        return userId;
    }

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

    @Id
    @Column(name = "SKILL_ID", nullable = false)
    public Long getSkillId() {
        return skillId;
    }

    public void setSkillId(Long skillId) {
        this.skillId = skillId;
    }

    @MapsId("userId")
    @ManyToOne
    @JoinColumn(name = "USER_ID", referencedColumnName = "USER_PROFILE_ID", nullable = false)
    public UserProfile getUserProfileByUserId() {
        return userProfileByUserId;
    }

    public void setUserProfileByUserId(UserProfile userProfileByUserId) {
        this.userProfileByUserId = userProfileByUserId;
    }

    @MapsId("skillId")
    @ManyToOne
    @JoinColumn(name = "SKILL_ID", referencedColumnName = "SKILL_ID", nullable = false)
    public Skill getSkillBySkillId() {
        return skillBySkillId;
    }

    public void setSkillBySkillId(Skill skillBySkillId) {
        this.skillBySkillId = skillBySkillId;
    }
}

И мои весенние данные jpa, которые обновляют объект выполняет свою работу, обновляя значения таблицы USER_PROFILE в БД, но мне нужно получить обновленное сопоставленное значение NATIONALITY_EN (поскольку я изменил идентификатор ссылочного столбца с 248 на 249), мне нужно повторно выполнить другой оператор SELECT, чтобы получить соответствующее значение NATIONALITY_EN . Даже это не относится к моему сопоставлению @OneToMany для List в объекте UserProfile, я получил обновленную информацию без необходимости повторного выбора из БД.

    @OneToMany(mappedBy = "userProfileByUserId", cascade = CascadeType.ALL)
    public List<UserSkills> getUserSkillsByUserProfileId() {
        return userSkillsByUserProfileId;
    }

И вот код, который отвечает за обновления

     dbUserProfile.setUserSkillsByUserProfileId(userProfileDataPOJO.getUserSkills()
                .stream()
                .map(skill -> new UserSkills(dbUserProfile, new Skill(skill.getSkillId())))
                .collect(Collectors.toList()));
     dbUserProfile.setBusinessUnitByBusinessUnitId(new BusinessUnit(userProfileDataPOJO.getBusinessUnit().getBusUntId()));
     dbUserProfile.setNationalityByNationalityId(new Nationality(userProfileDataPOJO.getNationality().getNationalityId()));
     dbUserProfile = userProfileDao.save(dbUserProfile);

     // after updating and getting the updated UserProfile object from the DB  
     dbUserProfile.getNationalityByNationalityId().getNationalityNameEn();   \\ this is always null ..
     dbUserProfile.getUserSkillsByUserProfileId();   \\ this always return the full needed object

Я спрашиваю, есть ли @annotation, который заставит объект Nationality действовать так же, как объект userSkills? потому что я не хочу делать еще один вызов select в БД для загрузки необходимого значения.

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 22 июля 2020

Итак, я просто запросил национальность через NationalityRepo, затем добавил недавно полученную сущность и добавил ее в UserProfile, таким образом я могу получить только соответствующее NationalityName для Id, который у меня есть. Кроме того, я боялся, что Hibernate выполнит еще один запрос, проверяя, что национальность существует в БД, прежде чем вставлять в UserProfile, но это не так, спасибо за кеш Hibernate.

1 голос
/ 20 июля 2020

Существует возможность извлекать вложенные объекты СРОЧНО, добавить этот 'fetch = FetchType.EAGER' в свою аннотацию @ManyToOne.

В качестве альтернативы вы можете использовать аннотации @Transactional вокруг метода извлечения объекта и вызвать Метод получения национальности в рамках этой транзакции. Таким образом, Hibernate по-прежнему будет иметь открытый сеанс и загружать вложенный объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...