Двойное исключение входа - PullRequest
0 голосов
/ 18 февраля 2019

Это пружинное приложение (без пружинной загрузки).База данных, которую я использую, - MySQL.У меня возникает проблема при сохранении сущности Driver, которая имеет отношение «многие к одному» на Carrier и Location.

Что я хочу сделать, это когда я сохраняю драйвер.Драйвер вместе с Location и Carrier сохраняется в базе данных.Проблема, с которой я сталкиваюсь - это когда я пытаюсь сохранить.Я получаю повторное нарушение ключа

Трассировка стека:

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;
    }

Вопрос: возможно ли достичь того, что я пытаюсь сделать?Ожидайте hibernate для обработки отношений, когда я попытаюсь сохранить и связать 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;
    }

Обновление № 2

Иметь такой репозиторий Driver

@Repository
public interface DriverRepository extends JpaRepository<Driver, Long> {

}

Для сохранения:

repository.saveAll(drivers);

Github link https://github.com/mukulgoel1989/greyhound

Я добавил ссылку на github на случай, если кто-то захочет попробовать.

Ответы [ 6 ]

0 голосов
/ 25 февраля 2019

Я приготовил рабочий раствор: 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 сущностей, или используйте новые .Таким образом, чтобы решить эту проблему, мы должны:

  1. Подготовить 3 репозитория для этих объектов.
  2. Для каждого «задания» найти , связанных Location и Carrier,
  3. Если Location и Carrier не найдены, создайте новые.
  4. Создайте новый Driver и установите найденные Location и Carrier или новыесоздал.
  5. Сохраните 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).Это позволило не только уменьшить размер данных, но и уменьшить количество дополнительных запросов SQL, которые Hibernate выполняет при хранении сложных объектов.Когда таблицы Location и Carrier заполнены, Hibernate не выполняет ненужных запросов для их поиска, а берет их данные из собственного кэша (вы можете увидеть это в журнале приложения).

PS Обратите внимание, что этоРешение не является оптимальным.ИМО, чтобы сделать его лучше, вы можете разделить основной процесс на две части: первая сохраняется с разными Location с и Carrier с, а вторая просто сохраняется Driver с, не находя Location с и Carrier с,Обе части исполняются с пакетной вставкой .

ОБНОВЛЕНИЕ

Ответвление с оптимальным решением: Cepr0 / greyhound-demo: async_and_batch_insert

Из-за асинхронного сохранения местоположений и носителей и пакетной вставки обработка занимает всего около 5 секунд.

0 голосов
/ 24 февраля 2019

Поскольку Location и Carrier являются версиями, и вы не устанавливаете версию в создаваемых вами экземплярах, Hibernate, вероятно, просто считает их новыми и пытается вставить их (в противном случае, если их потребуется обновить,В любом случае Hibernate не будет знать, какие версии сравнивать, поскольку в обновленных экземплярах он отсутствует).

Во-первых, вам необходимо:

  • извлечь существующие Location и Carrier экземплярыиз db и обновите их, если они не новы (вы знаете, проверяя, установлен ли id);
  • или правильно распространяете и устанавливаете атрибут версии вместе с id и бизнес-атрибутами.

Во-вторых, у вас также есть два варианта с текущими сопоставлениями сущностей (и заявленная цель, чтобы Hibernate сохранил весь граф должным образом):

  • , если вы не используете транзакции, тогда дляоба из вышеперечисленных вы должны прибегнуть к entityManager.merge(driver), чтобы все правильно либо вставить или обновить;
  • в противном случае и только если вы выберете первый вариантвыше и прочитайте существующие Location и Carrier экземпляры и вызовите repository.saveAll(drivers) в той же транзакции, тогда это сработает, потому что экземпляры драйвера будут сохранены, а операция PERSIST будет каскадно присоединена к все еще присоединенным экземплярам местоположения и носителя.

Существует (много) других возможностей в зависимости от архитектурных решений и соглашений, используемых в вашем проекте, то есть я бы никогда не каскадировал ВСЕ со стороны many на сторону one (пример нежелательных последствий - удаление), и в большинстве случаев я бы всегда явно сохранял сторону one отдельно, но решать вам.

0 голосов
/ 21 февраля 2019

Нам нужно передать идентификатор в виде имени столбца, на который есть ссылка.Сопоставьте объект «Местоположение», как показано ниже.

@OneToMany
@JoinColumn(name = "location_id", referencedColumnName = "id")
private List<Driver> drivers = new ArrayList<Driver>();
0 голосов
/ 21 февраля 2019

Двойная проблема возникает, когда идет вставка записей для обеих сторон.Решение состоит в том, чтобы пометить одну сторону как «сопоставленную» с другой.

, поэтому используйте в 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>();
0 голосов
/ 20 февраля 2019

Одним из способов решения этой проблемы было бы просто загрузить все местоположения и носителей, чтобы с помощью 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);
}

Это будет выглядеть примерно так.Это простой пример, потому что я не знаю фактического контекста.

0 голосов
/ 18 февраля 2019

Вам также необходимо заполнить 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, а не Hibernate:

@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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...