gpt4 book ai didi

java - 使用@MapsId 在双向@OneToOne 上级联

转载 作者:行者123 更新时间:2023-12-04 15:16:15 26 4
gpt4 key购买 nike

我在 spring boot 2.1.1.RELEASE 上工作,hibernate 5.3.7.FINAL

规则是,用户可以没有电话(phoneuser 中可以为空)但是,电话不能没有用户(userphone 中不为空。

实体:

@Entity
public class Phone {

@Id
private Long id;

@OneToOne
@MapsId
@JoinColumn(name = "id")
private User user;

public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}

public User getUser() {
return user;
}
public void setUser(final User user) {
this.user = user;
}
}

@Entity
public class User {

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

@OneToOne(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private Phone phone;

public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}

public Phone getPhone() {
return phone;
}
public void setPhone(final Phone phone) {
this.phone = phone;
}
}

Controller :

@RestController
@RequestMapping
public class UserController {

private final UserService userService;

public UserController(final UserService userService) {
this.userService = userService;
}

@GetMapping("/demo")
public void createUserAndAddPhone() {
final User user = new User();
userService.save(user);
final Phone phone = new Phone();

phone.setUser(user);
user.setPhone(phone);
userService.update(user);
}
}

存储库:

public interface UserRepository  extends PagingAndSortingRepository<User, Long> {
}

服务:

@Service
public class UserService {

private final UserRepository userRepository;

public UserService(final UserRepository userRepository) {
this.userRepository = userRepository;
}

@Transactional
public void save(final User user) {
userRepository.save(user);
}

@Transactional
public void update(final User user) {
userRepository.save(user);
}
}

表格:

CREATE TABLE `phone` (
`id` bigint(20) NOT NULL,
PRIMARY KEY (`id`)
);

CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)

应用程序代码:

spring:
datasource:
url: jdbc:mysql://localhost:3308/demo?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false&allowPublicKeyRetrieval=true
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
jpa:
database-platform: org.hibernate.dialect.MySQL5Dialect
hibernate:
ddl-auto: validate

xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
<scope>runtime</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

调用 GET http://localhost:8080/demo 给我一个错误:

org.hibernate.id.IdentifierGenerationException: attempted to assign idfrom null one-to-one property [com.example.demo.Phone.user]

当我注释掉 userService.save(user); 时,它会运行并生成:

insert into `user` 
values ( )

-- Generated identifier: 13, using strategy: org.hibernate.id.ForeignGenerator

insert into `phone` (`id`) values (?)
-- Binding parameter [1] as [BIGINT] - [13]

但如果 user 被持久化然后更新,它就不起作用(引发上述异常)

最佳答案

啊,最后,这是一个 hibernate 错误(HHH-12436)。

它可以通过以下用例在纯 hibernate 应用程序中重现:

Session session = sessionFactory.openSession();

Transaction tr1 = session.beginTransaction();
User user = new User();
session.persist(user);
tr1.commit();

Transaction tr2 = session.beginTransaction();
Phone newPhone = new Phone();
user.setPhone(newPhone);
newPhone.setUser(user);
session.merge(user);
tr2.commit();

session.close();

从上面的链接可以看出,它在 hibernate 5.4 分支中得到了修复。

附言我能够在最新的 5.3 版本 (5.3.18.Final) 中重现该问题

关于java - 使用@MapsId 在双向@OneToOne 上级联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64266219/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com