JPA отношение «многие ко многим»: объект (ы) не обновлен - PullRequest
0 голосов
/ 04 февраля 2020

У меня очень странная проблема с JPA, и я надеюсь получить подсказки, как ее решить. Я использую новейший сервер Payara Full с Eclipselink и новейшую PostgreSQL -database.

У меня простое двунаправленное отношение «многие ко многим». В EJB-транзакции я создаю объект-компанию, сохраняю его (entityManager.persist ()), создаю сотрудника, устанавливаю объект-компанию и persist (), затем добавляю сотрудника в коллекцию в объекте-компании и вызовите entitymanager.merge () ... все внутри одной транзакции (метод Stateless-EJB-publi c). => отношение смоделировано после подсказок Vlads (используйте наборы вместо списков и т. д.).

Теперь в другой транзакции я меняю сотрудника, сливаю () изменения и изменения обновляются в база данных. Таким образом, с точки зрения базы данных все в порядке (даже поле @Version обновляется соответствующим образом).

Но теперь, если я удаляю компанию, она удаляется из базы данных успешно, но в памяти , компания все еще там. И это становится еще более странным: даже если я назову refre sh для сотрудника, компания все еще будет указана в объекте, даже если его больше нет в базе данных.

Если я отмечу компанию и сотрудник как @Cachable (value = false), все работает нормально. Даже если вместо обновления сотрудника я вызову entityManager.getEntityManagerFactory (). GetCache (). EvictAll (), он также удаляет компанию из объекта empployee.

Возможно, проблема в структуре наследования ? Я очень озадачен тем, что вызов entityManager.refre sh (employee); не извлекает свежее / текущее состояние из базы данных.

И это не имеет значения, если я изменяю сторону связи (уже проверено).

И равно () / hashCode также реализован (без коллекций, в противном случае он будет создавать круги), но упоминаются простые свойства, чтобы можно было / можно было распознать изменения в другой транзакции.

Итак, кто-то может дать мне несколько подсказок, где искать ошибку? Отключение кэша или удаление кэша - это скорее взлом, чем решение; -).

Заранее большое спасибо ...

@MappedSuperclass
public abstract class PersistEntity implements Serializable {

    public static final String PROPERTY_NAME_ID = "_id";

    @Id
    @Column(name = "_id", length = 60)
    @Convert(converter = ObjectIdAttributeConverter.class)
    private ObjectId id;

    @Version
    @Column(name = "version")
    private Long version;

    // more simple properties

}


@MappedSuperclass
public abstract class PersistentExtEntity extends PersistentEntity {

    // only simple string properties

}


@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class BusElementEntity extends PersistentExternalEntity {

    // only simple string properties

}


@Entity
public class Company extends BusinessElementEntity {

    @OneToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH},  fetch = FetchType.EAGER)
    private Employee leader;

    @ManyToMany(cascade = {
            CascadeType.PERSIST,
            CascadeType.MERGE,
            CascadeType.REFRESH
    }, fetch = FetchType.LAZY)
    @JoinTable(name = "employee_company",
            joinColumns = @JoinColumn(name = "emp_id"),
            inverseJoinColumns = @JoinColumn(name = "comp_id")
    )
    private Set<User> employees = new HashSet<>();

    // ...

}


@Entity
public class Employee extends PersistentExtEntity {

    @ManyToMany(mappedBy = "emplyoees", fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
    private Set<Company> companies = new HashSet<>();

    // ...

}


@Stateless
public class CompanyRepository {

    @Inject
    EntityManager entityManager;

    public void createWithLeader(CreateCompanyRerquest request) {
        Employee leader = employeeRepository.create(request); // creates the emplyoee object and calls "persist()"
        Company company = new Company(request);
        company.setLeader(emplyoee);
        company.addEmplyoee(company.getLeader());
        company.getLeader().getCompanies().add(company);
        company.prePersist(); // this is an known eclipse bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=445272)
        entityManager.persist(company);
        entityManager.merge(company.getLeader());
    }


    public void deleteCompany(String externalCompanyId) {
        final Optional<Company> companyOptional = getByExternalId(externalCompanyId);
        Company dbCompany = companyOptional.orElseThrow(() -> new APIException(GlobalApiErrorCode.E4040001));
//        entityManager.refresh(dbCompany); // contains still the very old employee object
        dbCompany.getLeader().getCompanies().remove(dbCompany);
        entityManager.merge(dbCompany.getLeader());
        entityManager.remove(dbCompany);
}

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