java - JPA - Hibernar - OneToOne

CorePress2024-01-25  12

Tengo una relación OneToOne entre las tablas Usuario y Perfil definida así:

@Entity
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name="users", uniqueConstraints = { 
        @UniqueConstraint(columnNames = "username"),
        @UniqueConstraint(columnNames = "email")
    }
)
public class User implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int idUser;
    private String username;
    private String email;
    private String password;
    
    @OneToOne(cascade=CascadeType.ALL, orphanRemoval=true)  
    @JoinColumn(name="id_profile", referencedColumnName="idProfile")
    private Profile profile;
    
    @ManyToMany(fetch = FetchType.EAGER)
    private Set<Role> roles = new LinkedHashSet<Role>();

}
@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name="profile",
    uniqueConstraints = @UniqueConstraint(columnNames = "discordId")
)
public class Profile implements Serializable {
    
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int idProfile;
    private Date birthday;
    private String discordId;
    private String description; 
    @ElementCollection(fetch=FetchType.EAGER)
    private Set<String> spokenLanguages = new LinkedHashSet<String>();

    @OneToMany(fetch=FetchType.EAGER)
    private Set<ProfileGame> profileGames = new LinkedHashSet<>();
    
    @OneToOne(mappedBy="profile")
    private User user;
    
    @ManyToOne
    private TimeSlot timeSlot;
    
}

Luego ejecuto una prueba para crear algunos elementos fijos en mi base de datos:

Profile profile = this.profileRepository.save(Profile.builder()
                    .birthday(new Date())
                    .discordId("discord-" + i)
                    .description("Description de user-" + i)
                    .spokenLanguages(spokenLanguages)
                    .timeSlot(timeSlot)
                    .build());
            user.setProfile(profile);
            System.err.println(user);

Todo funciona bien aquí, System.err.println(usuario) devuelve valores correctos.

El problema proviene de la base de datos, que no "aplica" el id_profile en mi tabla de Usuarios:

¿Qué me perdí?

¿Las entidades son la misma tabla o una tabla diferente?

-code_mechanic

28/03/2021 a las 15:32

Diferentes tablas

- Zabón

28/03/2021 a las 15:39

Entonces, ¿por qué el campo id_profile está en la tabla de usuarios? Debe haber un campo user_id FK en el perfil, ¿no?

-code_mechanic

28/03/2021 a las 15:51

No sé cómo hacer eso... ¡Soy novato en Spring! :-/

- Zabón

28/03/2021 a las 16:08

1

Te recomiendo que leas un poco sobre el mapeo OneToOne, consulta este artículo

-code_mechanic

28/03/2021 a las 16:30



------------------------------------

Intenta hacer algo como esto:

Profile profile = Profile.builder()
   .birthday(new Date())
   .discordId("discord-" + i)
   .description("Description de user-" + i)
   .spokenLanguages(spokenLanguages)
   .timeSlot(timeSlot)
   .user(user)
   .build();
user.setProfile(profile);
profile = this.profileRepository.save(profile);

Utiliza una asociación @OneToOne bidireccional, por lo que debe asegurarse de que ambas partes esténEstamos sincronizados en todo momento.

Además, como necesita propagar el estado persistente al usuario, debe agregar cascade = CascadeType.ALL al Profile.user como se muestra a continuación:

@Entity
public class Profile implements Serializable {
    
    // ...

    @OneToOne(mappedBy="profile", cascade=CascadeType.ALL)
    private User user;
    
}

1

En realidad, no cambió nada.

- Zabón

28/03/2021 a las 16:20



------------------------------------

Usuario de clase:

@OneToOne(mappedBy = "user", cascade = CascadeType.ALL,
    fetch = FetchType.LAZY, optional = false)   
private Profile profile;

Perfil de clase:

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="id_user")
private User user;

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare