Hibernate.Многие ко многим выдают ошибку «org.hibernate.PersistentObjectException, переданная для сохранения» - PullRequest
0 голосов
/ 25 июня 2018

Я недавно использую Spring Boot и Hibernate, и я работаю над проектом, который имеет простую ассоциацию «многие ко многим». Спортивный центр имеет множество услуг и наоборот. Когда я пытаюсь ввести JSON, как это, чтобы создать новый спортивный центр и связать некоторые существующие услуги:

{
"name" : "SC1",
"address" : "Street 1111",
"description" : "A Sport center",
"email" : "sc@sc.com",
"phones" : [{"number" : "123456"}, {"number" : "654321"}],
"services" : [{"idService" : 1}, {"idService" : 2}],
"commune" : {"idCommune" : 1},
"users" : [{"idUser":62}]
}

Я получаю эту ошибку:

2018-06-25 03:56:32.670 DEBUG 20696 --- [nio-8080-exec-6] org.hibernate.SQL                        : insert into sport_center (address, Commune_idCommune, description, email, name) values (?, ?, ?, ?, ?)
2018-06-25 03:56:32.671 TRACE 20696 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [Street 1111]
2018-06-25 03:56:32.671 TRACE 20696 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [INTEGER] - [1]
2018-06-25 03:56:32.671 TRACE 20696 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [VARCHAR] - [A Sport center]
2018-06-25 03:56:32.671 TRACE 20696 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [VARCHAR] - [sc@sc.com]
2018-06-25 03:56:32.671 TRACE 20696 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [5] as [VARCHAR] - [SC1]
2018-06-25 03:56:32.800 DEBUG 20696 --- [nio-8080-exec-6] org.hibernate.SQL                        : insert into phone (number, Sport_center_idSport_Center) values (?, ?)
2018-06-25 03:56:32.800 TRACE 20696 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [123456]
2018-06-25 03:56:32.800 TRACE 20696 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [INTEGER] - [252]
2018-06-25 03:56:32.942 DEBUG 20696 --- [nio-8080-exec-6] org.hibernate.SQL                        : insert into phone (number, Sport_center_idSport_Center) values (?, ?)
2018-06-25 03:56:32.942 TRACE 20696 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [654321]
2018-06-25 03:56:32.942 TRACE 20696 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [INTEGER] - [252]
2018-06-25 03:56:33.368 ERROR 20696 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.eiffel.canchai.model.Service; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.eiffel.canchai.model.Service] with root cause

org.hibernate.PersistentObjectException: detached entity passed to persist: com.eiffel.canchai.model.Service

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

Не могли бы вы помочь мне с этим?

Мои занятия ниже:

SportCenter.java

@Entity
@Table(name = "sport_center")
public class SportCenter implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)    
@Column(name = "idSport_Center")
private Integer idSportCenter;

@Column(name = "name")
private String name;

@Column(name = "address")
private String address;

@Column(name = "description")
private String description;

@Column(name = "email")
private String email;

@JoinTable(name = "sport_center_has_user", joinColumns = {
    @JoinColumn(name = "Sport_center_idSport_Center", referencedColumnName = "idSport_Center")}, inverseJoinColumns = {
    @JoinColumn(name = "User_idUser", referencedColumnName = "idUser")})
@ManyToMany(cascade = CascadeType.ALL)
private List<User> users;


@JoinTable(name = "sport_center_has_service", joinColumns = {
@JoinColumn(name = "Sport_center_idSport_Center", referencedColumnName = "idSport_Center")}, inverseJoinColumns = {    
@JoinColumn(name = "Service_idService", referencedColumnName = "idService")})
@ManyToMany(cascade = CascadeType.ALL)    
private List<Service> services;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "sportCenter")
@JsonIgnore
private List<ImageField> imageFields;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "sportCenter")
@JsonIgnore
private List<Field> fields;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "sportCenter", fetch = FetchType.LAZY)
private List<Phone> phones;

@JoinColumn(name = "Commune_idCommune", referencedColumnName = "idCommune")
@ManyToOne(optional = false)    
private Commune commune;


public SportCenter() {
}

Service.java

@Entity
@Table(name = "service")
public class Service implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)    
@Column(name = "idService")
private Integer idService;

@Column(name = "name")
private String name;           

@ManyToMany(fetch = FetchType.LAZY, mappedBy = "services", cascade = CascadeType.ALL) 
@JsonIgnore
private List<SportCenter> sportCenters;

public Service() {
}

ServiceDao.java

@Repository
@Transactional
public class ServiceDao implements IServiceDao {

@PersistenceContext
private EntityManager entityManager;

@Override
public void save(Service entity) {
    entityManager.persist(entity);      
}

* * * * * * * * * * * * * * * * * * * * * * * * *

).

Контроллер

@Controller
@RequestMapping("/sportcenter")
@CrossOrigin
public class SportCenterController {

@Autowired
private ISportCenterService  sportCenterService;

@PostMapping("/register")
public ResponseEntity<?> registerSportCenter(@RequestBody SportCenter sc){      
    if (sc.getEmail().length() == 0 || sc.getName().length() == 0 || sc.getAddress().length() == 0 || sc.getPhones().size() == 0 || sc.getServices().size() == 0) {
        return new ResponseEntity(new ErrorMsg("Check parameters. One of them is missing"),HttpStatus.NO_CONTENT);
    }

    for (Phone p : sc.getPhones()) {
        p.setSportCenter(sc);           
    }

    for (Service s : sc.getServices()) {
        s.addSportCenters(sc);              
    }

    sportCenterService.save(sc);
    return new ResponseEntity(HttpStatus.OK);
}

Я думаю, что это, вероятно, ошибка сопоставления ассоциаций, но я не уверен.

Кроме того, если вы видите, что есть способ улучшить мой код, пожалуйста, дайте мне знать :) .. Советы всегда хороши.

Я использую Spring Boot V2.0.3 и Hibernate 5.3

Заранее спасибо!

1 Ответ

0 голосов
/ 26 июня 2018

Проблема здесь в том, что вы передаете событие persist от родителя к потомку.

Когда дочерний объект имеет ненулевой идентификатор, тогда hibernate предположит, что он уже существует.Поскольку вы получаете данные из службы отдыха, я думаю, дочерние объекты «Служба» не отсоединены.Отсюда возникает ошибка «Отдельная сущность передана для сохранения».

Сначала необходимо сохранить родительский объект, настроить дочерние объекты с помощью вызова слияния, затем связать родительский объект с дочерними объектами или избавиться от Cascade.All,

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