Jos*_*ara 4 spring hibernate jpa one-to-one flyway
我正在尝试与共享 PK 建立一对一的关系,但是在尝试了很多事情之后我陷入了困境......
我会尽量提供所有可能的信息:
我正在使用的技术:
数据源配置:
spring.datasource.url = jdbc:mysql://localhost:3306/customers?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true&useSSL=false
spring.datasource.username = admin
spring.datasource.password = root
spring.jpa.database-platform = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql = true
Run Code Online (Sandbox Code Playgroud)
数据库模型:
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "customer", schema = "customers")
public class Customer {
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
@Column(name = "customer_id", columnDefinition = "BINARY(16)")
private UUID customerId;
@OneToOne(mappedBy = "customer", cascade = CascadeType.ALL)
private Address address;
}
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "address", schema = "customers")
public class Address {
@Id
@Column(name = "address_id", columnDefinition = "BINARY(16)")
private UUID addressId;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
private Customer customer;
}
Run Code Online (Sandbox Code Playgroud)
Flyway 迁移文件:
CREATE SCHEMA IF NOT EXISTS CUSTOMERS;
CREATE TABLE CUSTOMERS.CUSTOMER
(
customer_id BINARY(16) NOT NULL PRIMARY KEY,
) ENGINE = InnoDB;
CREATE TABLE CUSTOMERS.ADDRESS
(
address_id BINARY(16) NOT NULL PRIMARY KEY,
) ENGINE = InnoDB;
ALTER table CUSTOMERS.ADDRESS
ADD CONSTRAINT fk_customer_address
FOREIGN KEY (address_id)
REFERENCES CUSTOMERS.CUSTOMER (customer_id);
Run Code Online (Sandbox Code Playgroud)
集成测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class CustomerRepositoryIntegrationTest {
@Autowired
private CustomerRepository cut;
@Test
public void testSaveAndDeleteCustomer() {
Address address = new Address();
Customer customer = new Customer();
customer.setAddress(address);
cut.save(customer);
Customer retrievedCustomer = cut.findAll().get(0);
assertEquals(customer, retrievedCustomer);
}
}
Run Code Online (Sandbox Code Playgroud)
错误:
ERROR] testSaveAndDeleteCustomer(com.foxhound.customers.repositories.CustomerRepositoryIntegrationTest) Time elapsed: 0.034 s <<< ERROR!
org.springframework.orm.jpa.JpaSystemException: attempted to assign id from null one-to-one property [com.foxhound.customers.models.Address.customer]; nested exception is org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [com.foxhound.customers.models.Address.customer]
at com.foxhound.customers.repositories.CustomerRepositoryIntegrationTest.testSaveAndDeleteCustomer(CustomerRepositoryIntegrationTest.java:47)
Caused by: org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [com.foxhound.customers.models.Address.customer]
at com.foxhound.customers.repositories.CustomerRepositoryIntegrationTest.testSaveAndDeleteCustomer(CustomerRepositoryIntegrationTest.java:47)
Run Code Online (Sandbox Code Playgroud)
预先感谢您的帮助。
干杯!
您不了解双向映射的工作原理,因此您需要仔细考虑。编码
@OneToOne(fetch = FetchType.LAZY)
@MapsId
private Customer customer;
Run Code Online (Sandbox Code Playgroud)
inAddress
使映射成为单向的。通常为了保存它,您需要设置customer
字段并保存它。
address.setCustomer(customer);
addressRepo.save(address);
Run Code Online (Sandbox Code Playgroud)
但是,您已经定义了双向映射并提供了级联注释。
@OneToOne(mappedBy = "customer", cascade = CascadeType.ALL)
private Address address;
Run Code Online (Sandbox Code Playgroud)
级联注释使您不必执行两个持久性操作(在您的代码中),但这并不意味着您不必在地址中设置客户字段。此外,正如您所注意到的,为了使级联操作起作用,您需要设置客户的地址字段。
customer.setAddress(address);
Run Code Online (Sandbox Code Playgroud)
因此,为了使代码正常工作,您需要更改它以在地址中设置客户。
Address address = new Address();
Customer customer = new Customer();
customer.setAddress(address);
address.setCustomer(customer);
customerRepo.save(customer);
Run Code Online (Sandbox Code Playgroud)
使用双向映射,您必须管理关系的双方或以单向方式使用它进行持久化,并以双向方式使用它进行检索。如果您添加级联注释,那么您还必须管理关系的双方以进行持久化。
归档时间: |
|
查看次数: |
442 次 |
最近记录: |