Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Problema com relacionamento ManyToOne

Oi pessoal, resolvi fazer um relacionamento many to one, só que o campo do id de relacionamento fica null no banco de dados.

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

package com.igaopk.userapi.users.entitys;

import jakarta.persistence.*;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;

@Entity(name = "cellphone")
@Table(name = "TB_CELLPHONES")
@Getter
@Setter
@Data
public class CellPhone implements Serializable {

    @Id
    @Column(name = "phone_id", unique = true)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name = "cell_phone")
    private String cellphone;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id" )
    private User user;

    public CellPhone() {

    }

    public CellPhone(String cellphone) {
        this.cellphone = cellphone;
    }

    @Override
    public boolean equals(Object obj) {
        if(obj instanceof String){
            var phone = (String) obj;
            return this.getCellphone().equals(phone);
        }

        if(obj instanceof CellPhone objCellphone){
            return objCellphone.getId() == this.getId();
        }

        return false;
    }
}
package com.igaopk.userapi.users.entitys;

import com.igaopk.userapi.users.dtos.CreateUserDTO;
import com.igaopk.userapi.users.dtos.UserDTO;
import com.igaopk.userapi.users.mappers.CellPhoneMapper;
import jakarta.persistence.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Table(name = "TB_USERS", schema = "public")
@Entity(name = "user")
@Data
@Getter
@Setter
@EqualsAndHashCode(of = "id")
public class User implements UserDetails {

    @Id
    @Column(name = "user_id", unique = true)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "full_name")
    private String fullName;

    @Column(name = "user_name", unique = true)
    private String userName;

    @Column(name = "user_password")
    private String password;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<CellPhone> cellPhones = new ArrayList<>();

    public User() {

    }

    public User(String fullName, String userName, String password, List<CellPhone> cellPhones) {
        this.fullName = fullName;
        this.userName = userName;
        this.password = password;
        this.cellPhones = cellPhones;
    }

    public User(CreateUserDTO createUserDTO) {
        this.fullName = createUserDTO.fullName();
        this.userName = createUserDTO.userName();
        this.password = createUserDTO.password();
        this.cellPhones = CellPhoneMapper.parseCellPhoneToObject(createUserDTO.cellPhones());
    }

    public void encryptPassword(PasswordEncoder passwordEncoder) {
        this.password = passwordEncoder.encode(this.password);
    }

    public void update(UserDTO userDTO) {
        if (!userDTO.fullName().isBlank()) {
            this.fullName = userDTO.fullName();
        }

        if (!userDTO.password().isBlank() || userDTO.password().length() < 4) {
            this.password = userDTO.password();
        }

        if (!userDTO.cellPhones().isEmpty()) {
            for (String cellphone : userDTO.cellPhones()) {
                List<String> newCellphones = new ArrayList<>();
                var cache = this.cellPhones.stream().toList();
                if (!cache.contains(cellphone)) {
                    newCellphones.add(cellphone);
                }

                this.cellPhones.addAll(CellPhoneMapper.parseCellPhoneToObject(newCellphones));
            }
        }
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return List.of(new SimpleGrantedAuthority("ROLE_USER"));
    }

    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return this.userName;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}
2 respostas

Alguém pode me ajudar?

solução!

Olá Igor!

Pelo código que você compartilhou, parece que você está utilizando a anotação @ManyToOne na classe CellPhone para definir o relacionamento many-to-one com a classe User. No entanto, o problema de o campo do ID de relacionamento (user_id) estar nulo no banco de dados pode estar relacionado ao momento em que você está persistindo os dados no banco de dados.

Quando você cria uma nova instância de CellPhone, você está associando-a a um usuário específico através da propriedade user, mas essa associação não está sendo persistida no banco de dados. O JPA (Java Persistence API) não irá automaticamente persistir essa associação no banco de dados se você não tiver cuidado com o processo de persistência.

Para garantir que a associação many-to-one entre CellPhone e User seja persistida corretamente no banco de dados, você deve seguir os seguintes passos:

  1. Antes de persistir uma instância de CellPhone, defina o usuário associado ao telefone.
  2. Verifique se o usuário associado ao telefone já está gerenciado (está no estado persistente) pelo JPA antes de persistir o telefone. Caso contrário, você deve persistir primeiro o usuário e, em seguida, associar o telefone a esse usuário persistido.
  3. Verifique se as configurações de cascata (cascade) estão definidas corretamente. Neste caso, você está usando CascadeType.ALL, o que significa que as operações de persistência, remoção e atualização serão cascata do User para os CellPhone associados. Certifique-se de que o User também seja persistido corretamente.

Por exemplo, se você estiver criando e persistindo um novo CellPhone, você pode fazer algo assim:

// Criando e persistindo o usuário primeiro
User user = new User("Nome do Usuário", "username", "senha", new ArrayList<>());
entityManager.persist(user);

// Criando o CellPhone e associando-o ao usuário
CellPhone cellPhone = new CellPhone("123456789");
cellPhone.setUser(user);

// Persistindo o CellPhone
entityManager.persist(cellPhone);

Certifique-se de que os passos acima estejam ocorrendo na sequência correta ao criar e persistir uma instância de CellPhone com uma associação many-to-one com um User. Isso deve resolver o problema de o campo user_id estar nulo no banco de dados. Lembre-se de também verificar o código do processo de persistência, para ter certeza de que tudo está sendo feito corretamente.