Нарушение ограничений весной JPA только на некоторых записях - PullRequest
0 голосов
/ 30 мая 2018

Я получаю исключение нарушенных ограничений для сущности Dependency, но это происходит только в старых записях.Моим последним изменением было добавление mappedBy=kpi -атрибута к родительскому объекту с именем KPIBusiness.

Я могу удалить вновь созданные родительские объекты, имеющие зависимости, но не старые.

KPIBusiness.java:

@Entity
public class KPIBusiness extends KPI {

    private Long businessProcessId;
    private String businessProcess;

    private Long eventId;
    private String event;

    @OneToMany(mappedBy="kpi", fetch = FetchType.EAGER, cascade=CascadeType.ALL)   
    private Set<Dependency> dependencies;
}

Dependency.java

@Entity
@Table(name="dependencies")
public class Dependency {
    @Id
    @GeneratedValue
    private Long did;

    public Long getDid() {
        return did;
    }

    public void setDid(Long did) {
        this.did = did;
    }   
    private AlertConstants.TRIGGER kpiType;

    private Long kpiId;

    @JsonIgnore
    @ManyToOne
    @JoinColumn(name="id", nullable=false)  
    private KPIBusiness kpi;
}

Исключение:

Вызвано: org.h2.jdbc.JdbcSQLException: Ссылочный Integrität verletzt: "FKSKW30595DULX9PLB990.KPIBUSINESS_DEPENDENCIES ЗАРУБЕЖНЫЙ КЛЮЧ (DEPENDENCIES_DID) ССЫЛКИ PUBLIC.DEPENDENCIES (DID) (33) "Нарушение ограничения ссылочной целостности:" FKSKW30595DULXL90POB2K9KT3I: PUBLENDENDENDENDENDENGENDENDENGUSDENGUSDENGYDENGENCYDENGYBYKKG .C.Оператор SQL: удалить из зависимостей где сделал =?[23503-196]

Я использовал этот код:

repository.delete(currentKPI);
repository.flush();

И сейчас рассматриваю возможность использования этого кода:

currentKPI.setDependencies(new HashSet<Dependency>());
currentKPI = repository.save(currentKPI);
repository.flush();//HACK delete at first try
repository.delete(currentKPI);
repository.flush();

Однако, похоже, чтоcurrentKPI.setDependencies(dependencies); не обновляет зависимости вообще.Я использую этот код, чтобы попытаться изменить зависимости:

Set<Dependency> dependencies = new HashSet<Dependency>();
for(RemoteKPINames kpi : tcsDependencies.getValue()) {
    Dependency dependency = new Dependency();
    dependency.setKpiId(kpi.getId());
    dependency.setKpiType(kpi.getType());
    dependency.setKpi(data);
    dependencies.add(dependency);
}

log.info("Setting dependencies in data object #={}", dependencies.size());
data.setDependencies(dependencies);

Ответы [ 2 ]

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

Ваш каскад предназначен для использования от родителя (KPIBusiness) к ребенку (Dependency).Это не будет работать в другую сторону.Ваш Dependency не будет (магическим образом) удален из любых коллекций, которые его содержат.

Опция 1:

Удалите Dependency из KPIBusiness и удали это.Ниже приведен пример кода:

// start a transaction
Dependency dependencyToBeDeleted;
KPIBusiness kpiBusiness;
...
kpiBusiness.getDependencies().remove(dependencyToBeDeleted);
dependencyRepository.remove(dependencyToBeDeleted);
// commit the transaction

Вариант 2:

Расширьте аннотацию @OneToMany для Set<Dependencies> с помощью orphanRemoval=true ( Пример ).Затем достаточно удалить Dependency из коллекции в KPIBusiness, и JPA автоматически удалит его из базы данных, когда на него больше не будут ссылаться.

Убедитесь, что вы полностью понимаете использование УДАЛИТЬ каскады и orphanRemoval .Всегда лучше получить ошибку вместо того, чтобы JPA молча удаляла вещи, которые вы никогда не хотели удалять.

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

EmployeeEntity.java

@Entity
@Table(name = "Employee")
public class EmployeeEntity implements Serializable
{
    private static final long serialVersionUID = -1798070786993154676L;
    @Id
    @Column(name = "ID", unique = true, nullable = false)
    private Integer           employeeId;
    @Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100)
    private String            firstName;
    @Column(name = "LAST_NAME", unique = false, nullable = false, length = 100)
    private String            lastName;

    @OneToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name="EMPLOYEE_ID")
    private Set<AccountEntity> accounts;

    //Getters and Setters Ommited
}

AccountEntity.java

@Entity
@Table(name = "Account")
public class AccountEntity implements Serializable
{
    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "ID", unique = true, nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Integer           accountId;
    @Column(name = "ACC_NO", unique = false, nullable = false, length = 100)
    private String            accountNumber;

    @OneToOne (mappedBy="accounts",  fetch = FetchType.LAZY)
    private EmployeeEntity employee;

}

Посмотрите на жирный шрифт в приведенном выше исходном коде для EmployeeEntity.Джава.Он определяет «cascade = CascadeType.ALL» и, по сути, означает, что любые изменения, произошедшие в EmployeeEntity, должны каскадироваться и в AccountEntity.Если вы сохраните сотрудника, все связанные учетные записи также будут сохранены в базе данных.Если вы удалите сотрудника, то все учетные записи, связанные с этим сотрудником, также будут удалены.Достаточно просто.

Но что, если мы хотим каскадировать только операции сохранения, а не операции удаления.Затем нам нужно четко указать его, используя приведенный ниже код.

@OneToMany(cascade=CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinColumn(name="EMPLOYEE_ID")
private Set<AccountEntity> accounts;

Теперь только когда методы save () или persist () вызываются с использованием экземпляра employee, тогда сохраняются только учетные записи.Если в сеансе вызывается любой другой метод, его влияние не повлияет на / каскадно для учетных записей.

Типы каскадов JPA

Типы каскадов, поддерживаемые архитектурой персистентности Java:как показано ниже:

  1. CascadeType.PERSIST: означает, что операции save () или persist () каскадно связаны со связанными объектами.
  2. CascadeType.MERGE: означает, что связанные сущности объединяются при владениисущность объединена.
  3. CascadeType.REFRESH: делает то же самое для операции refresh ().
  4. CascadeType.REMOVE: удаляет все связанные ассоциации сущностей с этим параметром при удалении сущности-владельца.
  5. CascadeType.DETACH: отсоединяет все связанные объекты, если происходит «ручное отсоединение».
  6. CascadeType.ALL: сокращение от всех вышеперечисленных каскадных операций.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...