É comum mapeamos, objetos do mundo real ou entidades de negócio em classes Java, essas classes, onde normalmente essas classes representam tabelas em nosso banco objeto relacional. O Java possui uma especificação que nos ajuda a fazer esse link entre nossas classes, o JPA, ele define as regras de implementação e uso, o Hibernate, por exemplo, é uma das bibliotecas e implementa a especificação

O Hibernate também possui uma implementação própria, que diverge da especificação JPA ,mas que foi usada como base para a especificação JPA.

Nesse post, veremos a implementação de um mapeamento um-para-um, faremos o mapeamento do relacionamento de User para UserProfile, onde, cada usuário pode ter apenas um perfil, já que não faz sentido um usuário possuir múltiplos perfis. Não veremos a parte de configuração de conexão, já que estamos usando Spring Boot, e essa parte está sendo tratada na auto-configuração.

Começaremos mapeando a classe User

@Entity
public class User implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  @Column(length = 20, nullable = false)
  private String username;

  @OneToOne(cascade = CascadeType.ALL)
  @JoinColumn(name = "user_profile_id")
  private UserProfile userProfile;

  public User() {
  }

  //getters... setters

}

Usamos a anotação @Entity para marcar a classe como uma entidade gerenciada pelo JPA, toda entidade , também deve conter uma @Id, onde mapeamos para o atributo id, dizemos também que esse atributo terá o valor gerado pelo próprio JPA, assim, não precisamos gerenciar esses valores na mão.

Para o relacionamento um-para-um, usamos a anotação @OneToOne no atributo userProfile , adicionamos o atributo cascade da anotação, com o valor ALL, para que quando persistimos o objeto de User, também irá persistir o UserProfile, automaticamente.

Também marcamos o atributo userProfile, com a anotação @JoinColumn, para sinalizar, que a chave estrangeira, será salva na tabela de User

Por fim, temos o mapeamento da classe UserProfile

@Entity
public class UserProfile implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  private String name;

  private String surName;

  private String email;

  public UserProfile() {
  }

}

Aqui, nenhuma novidade, não precisamos referenciar a classe User aqui, pois estamos usando um mapeamento uni-direcional, ou sejá, apenas a classe User vai referenciar UserProfile

Podemos testar se está tudo corretamente mapeado, com o seguinte teste

@RunWith(SpringRunner.class)
@DataJpaTest
public class UniDirectionalIT {

  @Autowired
  TestEntityManager entityManager;

  @Test
  public void doesCreateUserAndUserProfile(){
    User user = new User("testname", new UserProfile("FirstName" , "SecondName"));
    Object userId = entityManager.persistAndGetId(user);
    entityManager.flush();
    entityManager.clear();

    //clean first level cache, to guarantee that will hit the database again

    User user1 = entityManager.find(User.class, userId);

    assertThat(user1).isNotNull();
    assertThat(user1.getUserProfile()).isNotNull();
  }

}

Fontes no link.