简体   繁体   中英

hibernate: deleting entity in a one to many relationship

I have a following error:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`spindledb`.`section`, CONSTRAINT `FK_ftoru9cp83n512p9is8x3vo53` FOREIGN KEY (`scenario_id`) REFERENCES `scenario` (`scenario_id`))

Here are my classes:

Scenario:

@Entity
@Table(name = "scenario")
public class Scenario {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "scenario_id")
private int id;

@Column(name = "title", nullable = false)
private String title;

@NotNull
@DateTimeFormat(pattern = "dd/MM/yyyy")
@Column(name = "creation_date", nullable = false)
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
private LocalDate creationDate;

@ManyToOne
@LazyCollection(LazyCollectionOption.FALSE)
@JoinColumn(name = "id", nullable = false)
private User user;

@OneToMany(mappedBy = "scenario", orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
private Set<Plot> plotList = new HashSet<Plot>();

@OneToMany(mappedBy = "scenario", orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
private Set<Character> characterList = new HashSet<Character>();

@OneToMany(mappedBy = "scenario", cascade=CascadeType.ALL, orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
@OrderBy("sequence ASC")
private Set<Section> sectionList = new HashSet<Section>();

Section:

@Entity
@Table(name = "section")
public class Section {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "section_id")
private int id;

@Size(min = 4, max = 50)
@NotNull
@Column(name = "name")
private String name;

@NotNull
@Column(name = "type")
private String type = SectionType.TEXT.getSectionType();

@Column(name = "visibility")
private boolean visibility;

@NotNull
@Column(name = "sequence")
private int sequence;

@ManyToOne (cascade=CascadeType.ALL)
@LazyCollection(LazyCollectionOption.FALSE)
@JoinColumn(name = "scenario_id", nullable = false)
private Scenario scenario;

Controller:

    @RequestMapping(value = { "/delete-{id}-scenario" }, method = RequestMethod.GET)
public String deleteScenario(@PathVariable int id) {

    scenarioService.deleteScenarioById(id);
    return "redirect:/home";
}

Scenario service:

@Service("scenarioService")
@Transactional
public class ScenarioServiceImpl implements ScenarioService {

@Autowired
private ScenarioDao dao;

@Override
public Scenario findById(int id) {
    return dao.findById(id);
}

@Override
public void saveScenario(Scenario scenario) {
    dao.saveScenario(scenario);

}

public void updateScenario(Scenario scenario) {
    Scenario entity = dao.findById(scenario.getId());
    if(entity!=null){
        entity.setTitle(scenario.getTitle());
        entity.setCreationDate(scenario.getCreationDate());            
    }
}

@Override
public void deleteScenarioById(int id) {
    dao.deleteScenarioById(id);

}

Dao

@Repository("scenarioDao")
public class ScenarioDaoImpl extends AbstractDao<Integer, Scenario> implements ScenarioDao {

@Override
public Scenario findById(int id) {
    return getByKey(id);
}

@Override
public void saveScenario(Scenario scenario) {
    persist(scenario);

}

@Override
public void deleteScenarioById(int id) {

    Query query = getSession().createSQLQuery("delete from scenario where id = :id");
    query.setString("id", ""+id);
    query.executeUpdate();
}

I understand that the problem is that there may be a Section that can not exist without scenario. Right now however section table in database is empty and I still can't remove Scenario. Thanks for advice

use cascade=CascadeType.ALL with all @ManyToOne relations in class Scenario because if you are going to delete any Scenario from database it must not be referenced any where in data base.

the other way to delete is.

Serializable id = new Long(1); //your id
Object persistentInstance = session.load(Scenario.class, id);
if (persistentInstance != null) {
    session.delete(persistentInstance);
}

Deleting an entity via Query would bypass any Cascade settings you put via annotation.

I would suggest find the entity first by id, then delete the entity object:

Object scenario = session.load(Scenario.class, id);
if (scenario != null) {
    session.delete(scenario);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM