如何解决Spring KafkaListener失败,无法进行休眠一对一单向映射
我已经使用Spring数据JPA在Hibernate中建立了一对一关系模型。这是我的模特:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Nationalized;
import org.hibernate.annotations.Parameter;
@Data
@Entity
@Table(name = "parent")
public class Parent
{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "seq-gen")
@GenericGenerator(name = "seq-gen",strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",parameters = { @Parameter(name = "sequence_name",value = "test_seq") })
@Column(name = "id")
private Long id;
@Nationalized
@Column(name = "Name",length = 50,nullable = false)
private String name;
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.MapsId;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.Data;
import org.hibernate.annotations.Nationalized;
@Data
@Entity
@Table(name="child")
public class Child
{
@Id
private Long id;
@OneToOne
@MapsId
private Parent parent;
@Nationalized
@Column(name = "name",nullable = false)
private String name;
}
子表与父表具有外键关系,父表本身使用@MapsId
映射到子表的主键。请注意,这是单向关系。
我正在使用Spring data jpa的JpaRepository
将对象持久存储到数据库中。
public interface ParentRepository extends JpaRepository<Parent,Long>{}
public interface ChildRepository extends JpaRepository<Child,Long>{}
在Service类内部,我有一个简单的方法,该方法首先持久化Parent
对象,然后再持久化Child
对象。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ServiceImpl
{
@Autowired
private ParentRepository parentRepository;
@Autowired
private ChildRepository childRepository;
public void create()
{
Parent parent = new Parent();
parent.setName("Parent");
parent = parentRepository.save(parent);
System.out.println(parent.getId());
Child child = new Child();
child.setName("Child");
child.setParent(parent);
childRepository.save(child); // This line fails when using ControllerKafka
}
}
我创建了一个RESTful控制器,该控制器具有自动连接的ServiceImpl
对象,它调用Service类的适当方法。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ControllerRestful
{
@Autowired
private ServiceImpl service;
@PostMapping(value = "/test")
@ResponseStatus(HttpStatus.OK)
public void create(@RequestBody UserDTO dto)
{
System.out.println(dto);
service.create();
System.out.println("Done");
}
}
请注意,Service类独立于Controller。我在本地测试了该终结点,并将其父对象和子对象持久保存到数据库中。
现在,当我切换到基于kafka的控制器时,它在持久化时会引发错误。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
@Controller
public class ControllerKafka
{
@Autowired
private ServiceImpl service;
@KafkaListener(topics = "..",groupId = "..")
@SendTo
public void create(UserDTO dto,Acknowledgment acknowledgment)
{
service.create();
System.out.println("Done");
acknowledgment.acknowledge();
}
}
错误日志:
org.springframework.kafka.listener.ListenerExecutionFailedException: Listener method 'public void ControllerKafka.create(UserDTO,org.springframework.kafka.support.Acknowledgment)' threw exception;
nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: models.Parent;
nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: models.Parent;
nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: models.Parent;
nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: models.Parent
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.decorateException(KafkaMessageListenerContainer.java:1899) ~[spring-kafka-2.5.2.RELEASE.jar:2.5.2.RELEASE]
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeErrorHandler(KafkaMessageListenerContainer.java:1887) ~[spring-kafka-2.5.2.RELEASE.jar:2.5.2.RELEASE]
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeRecordListener(KafkaMessageListenerContainer.java:1792) ~[spring-kafka-2.5.2.RELEASE.jar:2.5.2.RELEASE]
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeWithRecords(KafkaMessageListenerContainer.java:1719) ~[spring-kafka-2.5.2.RELEASE.jar:2.5.2.RELEASE]
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeRecordListener(KafkaMessageListenerContainer.java:1617) ~[spring-kafka-2.5.2.RELEASE.jar:2.5.2.RELEASE]
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeListener(KafkaMessageListenerContainer.java:1348) ~[spring-kafka-2.5.2.RELEASE.jar:2.5.2.RELEASE]
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.pollAndInvoke(KafkaMessageListenerContainer.java:1064) ~[spring-kafka-2.5.2.RELEASE.jar:2.5.2.RELEASE]
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:972) ~[spring-kafka-2.5.2.RELEASE.jar:2.5.2.RELEASE]
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) ~[na:na]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
在Child
情况下在ServiceImpl
内持久保存ControllerKafka
对象,而在ControllerRestful
中怎么可能失败?同样,如果我从@MapsId
中删除了Child
属性,并且对Child
实体使用了不同的主键和外键,那么持久化时就不会出错。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。