I have a class mapped with hibernate, however, when saving an object the whole object is cascaded to the child table (which is expected). The problem is that equal objects are saved instead of just relating the child object to the parent object.
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@Fetch(value = FetchMode.SELECT)
private List<Atributo> atributos;
I thought putting equals
would be enough for the API, but it did not work as expected.
Does anyone know how to do this so that I do not need to check if the object exists in the database every time the function is called?
In the example I made it looks like this:
@Entity
public class TestePai implements Serializable {
@Id
@GeneratedValue
private Long ID;
String name;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
TesteFilho testefilho;
}
@Entity
public class TesteFilho implements Serializable {
@Id
@GeneratedValue
private Long ID;
String name;
}
I used a task to execute.
@Component
public class TesteScheduller {
private static final Logger log = LoggerFactory.getLogger(UserAdminConfig.class);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
@Autowired
TestePaiRepository testePaiRepository;
@Autowired
TesteFilhoRepository testeFilhoRepository;
@Scheduled(initialDelay = 2000L, fixedRate = 24 * 60 * 60 * 1000L)
public void teste() {
log.trace("\n\n********************************************************************\n\n");
log.trace("Start TesteScheduller in: {}", dateFormat.format(new Date()));
TestePai pai = new TestePai();
TesteFilho filho = new TesteFilho();
if (this.testeFilhoRepository.findOneByName(filho.getName()) != null) {
filho = this.testeFilhoRepository.findOneByName(filho.getName());
}
pai.setTestefilho(filho);
log.trace("Pai 1:\n" + pai);
testePaiRepository.saveAndFlush(pai);
log.trace("\n\n********************************************************************\n\n");
pai = new TestePai();
pai.setName("Bom dia");
filho = new TesteFilho();
if (this.testeFilhoRepository.findOneByName(filho.getName()) != null) {
filho = this.testeFilhoRepository.findOneByName(filho.getName());
}
pai.setTestefilho(filho);
log.trace("Pai 1:\n" + pai);
testePaiRepository.save(pai);
testePaiRepository.saveAndFlush(pai);
}
}
This returns me the following error:
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.andersoney.teste.model.Teste.TesteFilho; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.andersoney.teste.model.Teste.TesteFilho
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:299)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:503)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:209)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy95.saveAndFlush(Unknown Source)
at com.andersoney.teste.scheduller.TesteScheduller.teste(TesteScheduller.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
The main challenge in the real situation is that I will apply what is discovered here: the object will have many children, a list ManytoMany
, and in this list there will be both objects that exist, and objects other than the database. I can do the check as above and add the object already with the% set% of the bank. But the foreign key must be persisted for those who have ID
, and those that you do not have, the foreign key like Hibernate must already be saved and fetched.