这是一个Spring应用程序(没有Spring Boot)。
我正在使用的数据库是MySQL。
我遇到的问题是保存实体Driver
时,该实体在Carrier
和Location
上都具有多对一关系。
当我在Driver上进行保存时,我想做的是。驱动程序以及位置和运营商将持久保存到数据库中。我遇到的问题是尝试保存时。我收到重复的密钥冲突
堆栈跟踪:
org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1062, SQLState: 23000
Feb 18, 2019 1:25:42 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Duplicate entry '910327' for key 'UK_lheij6i9eldhfhyu9j1q5fjls'
Exception in thread "main" org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [UK_lheij6i9eldhfhyu9j1q5fjls]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:296)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:253)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy47.saveAll(Unknown Source)
at greyhound.service.GreyhoundServiceImpl.process(GreyhoundServiceImpl.java:38)
at greyhound.Main.main(Main.java:17)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:178)
at org.hibernate.dialect.identity.GetGeneratedKeysDelegate.executeAndExtract(GetGeneratedKeysDelegate.java:57)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3073)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3666)
at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:645)
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:282)
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:263)
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:317)
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:332)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:289)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:196)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:127)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:828)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:795)
at org.hibernate.engine.spi.CascadingActions$7.cascade(CascadingActions.java:298)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:490)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:415)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:216)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:149)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:428)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:266)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:196)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:127)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:804)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:308)
at com.sun.proxy.$Proxy44.persist(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:489)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAll(SimpleJpaRepository.java:521)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAll(SimpleJpaRepository.java:73)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:359)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:644)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:608)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$invoke$3(RepositoryFactorySupport.java:595)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:595)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 11 more
Caused by: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '910327' for key 'UK_lheij6i9eldhfhyu9j1q5fjls'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:970)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1109)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1057)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1377)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1042)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)
... 69 more
Process finished with exit code 1
实体/模型类:(已删除获取器/设置器)
@Entity
@Table(name = "Driver")
public class Driver {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Version
@Column(name = "version")
private int version;
@Column(name = "driver_id")
private Long driverId;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "middle_init")
private String middleInitial;
@ManyToOne(fetch = FetchType.EAGER)
@Cascade({CascadeType.ALL})
private Carrier carrier;
@ManyToOne(fetch = FetchType.EAGER)
@Cascade({CascadeType.ALL})
private Location location;
@Entity
@Table(name="Carrier")
public class Carrier {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Version
@Column(name = "version")
private int version;
@PrimaryKeyJoinColumn
@Column(name = "carrier_name")
private String carrierName;
@OneToMany
@JoinColumn(name = "carrier_id", referencedColumnName = "id")
@Entity
@Table(name="Locations")
public class Location {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Version
private Long version;
@Column(name = "location_id")
private Long locationId;
@Column(name = "location_name")
private String locationName;
@OneToMany
@JoinColumn(name = "location_id", referencedColumnName = "location_id")
private List<Driver> drivers = new ArrayList<Driver>();
}
编写实体的代码
private List<Driver> prepareEntityList(Result result) {
List<Driver> drivers = new ArrayList<Driver>();
for(DriverAssignment driverAssignment : result.getDriverAssignments()) {
Location location = new Location();
location.setLocationName(driverAssignment.getHomeLocation3());
location.setLocationId(driverAssignment.getHomeLocation());
Carrier carrier = new Carrier();
carrier.setCarrierName(driverAssignment.getCarrierId());
Driver driver = new Driver();
driver.setDriverId(driverAssignment.getDriverId());
driver.setFirstName(driverAssignment.getFirstName());
driver.setLastName(driverAssignment.getLastName());
driver.setMiddleInitial(driverAssignment.getMiddleInitial());
driver.setCarrier(carrier);
driver.setLocation(location);
drivers.add(driver);
}
return drivers;
}
问题:是否有可能实现我想做的事情?如果我尝试保存location
和driver
并将其与@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "greyhound" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/greyhound1");
dataSource.setUsername("root");
dataSource.setPassword("");
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
return properties;
}
关联,则希望休眠处理这些关系,如果它已经保存而不是尝试再次保存。
如果没有,建议的保存这些实体的方法是什么?
数据源配置
@Repository
public interface DriverRepository extends JpaRepository<Driver, Long> {
}
更新#2
具有这样的DriverRepository
repository.saveAll(drivers);
要保存:
quad
Github链接 https://github.com/mukulgoel1989/greyhound
我添加了github链接,以防有人愿意尝试。
答案 0 :(得分:4)
我准备了有效解决方案:Cepr0/greyhound-demo。 我稍微修改了您的项目-使用Spring-Boot,Lombok和H2数据库完成了该项目,仅出于演示目的并简化它。
因此,如果我没记错的话,任务是转换“ 任务”(从灵缇犬网站开始):
{
"results": [
{
"oper_nbr": 1,
"carrier_cd": "GLX ",
"last_name": "JOHN",
"first_name": "SMITH",
"middle_init": null,
"home_loc_6": 12345,
"home_loc_3": "NLX",
"oper_class": "T"
},
{
"oper_nbr": 2,
"carrier_cd": "GLX ",
"last_name": "JOHN",
"first_name": "DOE",
"middle_init": null,
"home_loc_6": 67890,
"home_loc_3": "NLX",
"oper_class": "T"
}
]
}
三个实体: Driver
, Location
和 Carrier
,它们之间的关系:
Location -1---*- Driver -*---1- Carrier
即Driver
与Location
和Carrier
具有“多对一”关系。
此任务的主要问题是,在保存Driver
实体时,我们需要使用已经持久保存的 Location
和Carrier
实体,或者使用新的。因此,要解决它,我们必须:
Location
”和“ Carrier
”相关的“任务” 查找。 Location
和Carrier
,则创建新的。Driver
并设置找到的Location
和Carrier
或已创建的新对象。Driver
(如果找不到,则级联保持Location
和Carrier
)。方法GreyhoundService.process()
的最终代码:
@Transactional
public void process() {
client.getAssignments()
.stream()
.forEach(a -> {
log.debug("[d] Assignment: {}", a);
Driver driver = new Driver();
driver.setId(a.getDriverId());
driver.setFirstName(a.getFirstName());
driver.setLastName(a.getLastName());
driver.setMiddleName(a.getMiddleName());
driver.setLocation(
locationRepo.findById(new Location.PK(a.getLocationId(), a.getLocationName()))
.orElse(new Location(a.getLocationId(), a.getLocationName()))
);
driver.setCarrier(
carrierRepo.findById(a.getCarrierId().trim())
.orElse(new Carrier(a.getCarrierId().trim()))
);
driverRepo.saveAndFlush(driver);
log.debug("[d] Driver: {}", driver);
});
}
为了最小化数据库中数据的大小和SQL选择的数量,我对初始实体进行了如下转换:
驱动程序
@Getter
@Setter
@ToString
@EqualsAndHashCode(of = "id")
@Entity
@Table(name = "drivers")
public class Driver implements Persistable<Long> {
@Id private Long id;
private String firstName;
private String lastName;
private String middleName;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "carrierId", foreignKey = @ForeignKey(name = "drivers_carriers"))
private Carrier carrier;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumns(
value = {@JoinColumn(name = "locationId"), @JoinColumn(name = "locationName")},
foreignKey = @ForeignKey(name = "drivers_locations")
)
private Location location;
@Override
public boolean isNew() {
return true;
}
}
位置
@Data
@NoArgsConstructor
@Entity
@Table(name = "locations")
@IdClass(Location.PK.class )
public class Location {
@Id private Long locationId;
@Id private String locationName;
public PK getId() {
return new PK(locationId, locationName);
}
public void setId(PK id) {
this.locationId = id.getLocationId();
this.locationName = id.getLocationName();
}
public Location(final Long locationId, final String locationName) {
this.locationId = locationId;
this.locationName = locationName;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class PK implements Serializable {
private Long locationId;
private String locationName;
}
}
运营商
@Data
@NoArgsConstructor
@Entity
@Table(name = "carriers")
public class Carrier {
@Id private String carrierId;
public Carrier(final String carrierId) {
this.carrierId = carrierId;
}
}
如您所见,我使用了Location
和Carrier
的自然标识符(以及Carrier
中的复合标识符)。这样不仅可以减少数据的大小,而且可以减少Hibernate在存储复杂实体时执行的其他SQL查询的数量。填充Location
和Carrier
表后,Hibernate不会执行不必要的查询来查找它们,而是从其自己的缓存中获取数据(您可以在应用程序日志中看到它)。
P.S。请注意,此解决方案不是最佳的。 IMO为了使它更好,您可以将主要过程分为两部分:第一个过程持久保存不同的Location
和Carrier
,而第二个过程持久保存Driver
s而没有找到{{1 }}和Location
。这两个部分都与batch insert一起执行。
更新
以最佳解决方案分支:Cepr0/greyhound-demo:async_and_batch_insert
由于位置和运营商的异步保留以及批量插入,处理仅需约5秒钟。
答案 1 :(得分:1)
由于Location
和Carrier
已经过版本控制,并且您没有在创建的实例中设置版本,因此Hibernate可能只会认为它们是新的并尝试插入它们(否则,如果需要它们要进行更新,Hibernate始终不知道要比较哪个版本,因为更新的实例中缺少该版本。
首先,您需要:
Location
和Carrier
实例,如果它们不是新的,则对其进行更新(通过检查是否设置了id即可知道); 第二,在当前的实体映射中,您还有两种选择(以及让Hibernate正确保存整个图形的既定目标):
entityManager.merge(driver)
,以便正确插入或更新所有内容; Location
和Carrier
实例并在同一事务中调用repository.saveAll(drivers)
时,它才会起作用,因为驱动程序实例将是持久化,PERSIST
操作将级联到仍附加的位置和载体实例。根据您项目中使用的体系结构选择和约定,还有(许多)其他可能性,即,我永远不会从many
到one
这边层叠ALL(一个不希望的结果是删除) ,而且在大多数情况下,我总是会分别明确地保存one
面,但这取决于您。
答案 2 :(得分:0)
您还需要在Carrier
和Location
中使用已包装的Driver
:
for(DriverAssignment driverAssignment : result.getDriverAssignments()) {
Location location = new Location();
Carrier carrier = new Carrier();
Driver driver = new Driver();
driver.setCarrier(carrier);
driver.setLocation(location);
// add this
location.getDrivers().add(driver);
carrier.getDrivers().add(driver);
drivers.add(driver);
}
由于您使用了双向映射(@OneToMany
),因此需要完成此操作
更新:
使用JPA级联配置,而不是休眠一个:
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Carrier carrier;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Location location;
更新2
仔细查看您的项目后,您似乎缺少以下事务设置:
@Transactional
public void process() {
在该方法内,您将执行许多存储库操作,这很好,因为所有SimpleJpaRepository方法都是事务性的。
我认为问题在于,并非所有这些操作都在同一事务下并有效地实现了持久化。 (每个操作都在自己的小事务内运行,然后所有实体都与持久性上下文分离)。
注意:您可能需要进行一些配置才能启用@Transactional注释设置。
答案 3 :(得分:0)
解决此问题的一种方法是仅加载所有位置和载体,因此使用findById()将它们绑定到您的会话。使用这些获得的对象在新的驱动程序对象上进行设置。这应该可以解决问题。
for(DriverAssignment driverAssignment : result.getDriverAssignments()) {
Location location;
if (driverAssignment.getHomeLocation() != null) {
location = locationRepo.findById(driverAssignment.getHomeLocation());
} else {
location = new Location();
}
location.setLocationName(driverAssignment.getHomeLocation3());
Carrier carrier;
if (driverAssignment.getCarrierId() != null) {
carrier = carrierRepo.findById(driverAssignment.getCarrierId());
} else {
carrier = new Carrier();
}
Driver driver;
if (driverAssignment.getDriverId() != null) {
driver = driverRepo.findById(driverAssignment.getCarrierId());
} else {
driver = new Driver();
}
driver.setDriverId(driverAssignment.getDriverId());
driver.setFirstName(driverAssignment.getFirstName());
driver.setLastName(driverAssignment.getLastName());
driver.setMiddleInitial(driverAssignment.getMiddleInitial());
driver.setCarrier(carrier);
driver.setLocation(location);
drivers.add(driver);
}
看起来像这样。这只是一个简单的示例,因为我不知道实际的上下文。
答案 4 :(得分:0)
当它要在双方插入条目时导致重复的问题。 解决方案是将一侧标记为另一侧“映射”。
因此可在Carrier
类中使用:
@OneToMany(mappedBy="carrier")
@JoinColumn(name = "carrier_id", referencedColumnName = "id")
private List<Driver> drivers = new ArrayList<Driver>();
在Location
类中:
@OneToMany(mappedBy="location")
@JoinColumn(name = "location_id", referencedColumnName = "location_id")
private List<Driver> drivers = new ArrayList<Driver>();
答案 5 :(得分:0)
我们需要将标识符作为引用的列名进行传递。如下所示映射位置实体。
@OneToMany
@JoinColumn(name = "location_id", referencedColumnName = "id")
private List<Driver> drivers = new ArrayList<Driver>();