Estoy usando la primavera de datos y anotación @Transactional (por rollback automático después de las pruebas). Tengo relación bidireccional simple entre la cuenta y el usuario (lado propietario):
@Entity
@Table(name = "ACCOUNT_T")
public class AccountEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String email;
private String password;
private String verificationCode;
private Boolean active = false;
@OneToOne(mappedBy = "account", fetch = FetchType.EAGER,
cascade = {CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.DETACH, CascadeType.REFRESH})
private UserEntity user;
}
@Entity
@Table(name = "USER_T")
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String surname;
private String phone;
private LocalDate birthDate;
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@JoinColumn(name = "account_id")
private AccountEntity account;
}
Estoy usando JpaRepositories y obtenerlos se fija a ansiosos. ¿Por qué a veces cuando consigo los objetos de la base de datos no puedo conseguir es devuelto a su hijo objetos nulo. Depende de qué lado agrego objetos. He escrito prueba simple usando Junit5:
@ExtendWith(SpringExtension.class)
@SpringBootTest
@Transactional
class UserAndAccountRepositoriesTest {
void testA() {
UserEntity userEntity = new UserEntity();
setUserProperties(userEntity);
AccountEntity accountEntity = new AccountEntity();
setAccountProperties(accountEntity); //just setting values for fields
accountEntity.setUser(userEntity);
accountRepository.save(accountEntity);
accountRepository.findAll().get(0).getUser(); //returns user
userRepository.findAll().get(0).getAccount(); //returns null,but should return account related to that user
}
void testB() {
UserEntity userEntity = new UserEntity();
setUserProperties(userEntity);
AccountEntity accountEntity = new AccountEntity();
setAccountProperties(accountEntity);
accountEntity.setUser(userEntity);
accountRepository.save(accountEntity);
accountRepository.findAll().get(0).getUser(); //again returns null,but shouldn't
userRepository.findAll().get(0).getAccount(); //returns account
}
}
Sin @Transactional
todo funciona bien - no estoy recibiendo nula. ¿Qué estoy haciendo mal?
Que había necesidad de ajustar ambos lados de una relación para definir explícitamente. Trate de añadir userEntity.setAccount(accountEntity)
durante su caso de configuración, esto sería resolver el problema.
Hibernate no le ayudará y asumir sólo porque se establece a -> b
, que establecería b <- a
para usted dentro de la otra entidad.
La razón por la que podría funcionar sin @Transactional
es que, sin la anotación que se está comprometiendo los datos de configuración en cualquier fuente de datos que está utilizando, y nada se rollback al final, y ya que usted está seleccionando los datos sin ningún tipo id
con findAll
, que está recibiendo usuario anterior / ENTIDADES cuenta que ya se han cometido, algunos con relación y algunos sin, por lo tanto el error aleatorio que está recibiendo.