JpaRepository save () создает новые дочерние объекты вместо обновления - PullRequest
0 голосов
/ 26 мая 2018

В настоящее время я конвертирую приведенный ниже JSON в два Java-объекта, используя GSON.Объект Company содержит объект Accounts в соотношении один к одному.

JSON:

{
  "company_name": "ETHEREUM LTD",
  "accounts": {
    "next_made_up_to": "2018-11-30",
    "next_due": "2019-08-31"
  },
  "company_number": "11090535"
}

Объект Company:

@Data
@Entity
@Table(name = "companies")
public class Company {

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

    @OneToOne(cascade=CascadeType.ALL)
    private Accounts accounts;

    @NotNull
    @SerializedName("company_number")
    @Column(unique = true)
    private String companyNumber;

    @SerializedName("company_name")
    private String companyName;

    public Company() {}

    public Company(String companyNumber) {
        this.companyNumber = companyNumber;
    }
}

Объект Accounts:

@Data
@Entity
@Table(name = "accounts")
public class Accounts {

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

    @SerializedName("next_due")
    private Date nextDue;

    @SerializedName("next_made_up_to")
    private Date nextMadeUpTo;
}

Я реализовал Spring Data JpaRepository для сохранения этих объектов в моей базе данных.

public interface CompanyRepository extends JpaRepository<Company, Long> {
}

У меня есть метод для обновления всех объектов Company в базе данных новой информацией JSON.

@Scheduled(fixedRate = 50000)
public void updateAllCompanies() {
    System.out.println("Starting update!");
    for(Company company : companyRepository.findAll()) {
        Long companyId = company.getId();
        Long accountsId = null;
        if(company.getAccounts() != null) {
            accountsId = company.getAccounts().getId();
        }
        company = getCompany(company.getCompanyNumber());
        company.setId(companyId);
        if(accountsId != null) {
            company.getAccounts().setId(accountsId);
        }
        companyRepository.save(company);
    }
}

Если я вручную не установил идентификаторы как для родительского, так и для дочернего объекта, эти объекты создаются как новые записи базы данных, а не как обновления существующих записей.Есть ли лучший способ справиться с этим, чем вручную устанавливать идентификаторы в Java?

1 Ответ

0 голосов
/ 26 мая 2018

Если я вручную не установил идентификаторы как для родительского, так и для дочернего объекта, эти объекты создаются как новые записи базы данных, а не как обновления существующих записей.

Так работает каждый поставщик персистентности.

Если поле @Id сущности не помечено для автоматической генерации провайдером постоянства или базой данных, то наличие нулевого значения заставит провайдера вызвать исключение.Однако, если поле помечено для автоматического создания поставщиком или базой данных, оно пропустит исключение и будет рассматривать объект как новый экземпляр, который необходимо вставить.Только при наличии значения в поле идентификатора будет инициировано обновление существующей строки.

Есть ли лучший способ справиться с этим, чем ручная установка идентификаторов в Java?

Это зависит.

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

Если это неправдоподобный вариант, вам потребуется назначить их, если вы собираетесь использовать @Entity для представления вашего Accounts.

Я не уверен, является ли ваша сущность Accounts ссылкой на что-либо еще в вашей модели данных.Но здесь нужно учитывать одну вещь: насколько мощно @ElementCollection встраиваемых объектов может очень легко решить вашу проблему с идентификатором:

@Embeddable 
public class Accounts implements Serializable {
  private Date nextDue;
  private Date nextMadeUpTo;
  // implement proper equals/hashcode here
}

@Entity
public class Customer {
  // your normal things
  @ElementCollection
  private Set<Accounts> Accounts;
}

Теперь все, что вам нужно сделать, это добавить все данные, которые ваш JSON получает в Accounts и поместите его в коллекцию элементов.Затем Hibernate позаботится о том, чтобы определить, нужно ли вам что-либо удалять или вставлять, используя таблицу сбора, например, следующим образом:

CUSTOMER_ID | NEXT_DUE | NEXT_MADE_UP_TO

Правильное использование equals / hashCode наAccounts встраиваемый гарантирует отсутствие дубликатов, он также помогает определить, что изменено или нет.Базовая таблица коллекции теперь использует все поля встраиваемого элемента + первичный ключ Customer в качестве первичного ключа таблицы.Это позволяет избежать проблемы с суррогатным первичным ключом, используя в качестве данных естественные ключи.

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