【问题标题】:Updating creates new child object instead of updating the existing one Hibernate更新会创建新的子对象,而不是更新现有的 Hibernate
【发布时间】:2018-05-09 14:37:48
【问题描述】:

在我的 Spring Boot 应用程序中,我有一个 Workout 对象,其中包含一个锻炼对象列表。问题是当我尝试更新锻炼时,属于锻炼的锻炼没有被更新。相反,它在数据库中创建新的练习对象。我在下面添加了我的锻炼实体和锻炼实体。任何帮助将不胜感激。

锻炼班:

@Entity
public class Workout {

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


@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "workout_id")
private List<Exercise> exercises;

public Workout(List<Exercise> exercises) {
    this.exercises = exercises;
}

public Workout() {
}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public List<Exercise> getExercises() {
    return exercises;
}

public void setExercises(List<Exercise> exercises) {
    this.exercises = exercises;
}
}

练习课:

@Entity
@Table
public class Exercise {

@Id
@GeneratedValue
private Long id;


private String exerciseName;
private int weight;
private int actualReps;

@ManyToOne
@JoinColumn(name = "workout_id")
private Workout workout;

public Exercise(){}


public Exercise( String exerciseName, int weight, int actualReps) {
    this.exerciseName = exerciseName;
    this.weight = weight;
    this.actualReps = actualReps;
}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getExerciseName() {
    return exerciseName;
}

public void setExerciseName(String exerciseName) {
    this.exerciseName = exerciseName;
}

public int getWeight() {
    return weight;
}

public void setWeight(int weight) {
    this.weight = weight;
}

public int getActualReps() {
    return actualReps;
}

public void setActualReps(int actualReps) {
    this.actualReps = actualReps;
}
}

控制器:

@Controller
public class WorkoutController {

@Autowired
private WorkoutService workoutService;
@Autowired
private OneRepMaxService oneRepMaxService;
@Autowired
private ActualRepsService actualRepsService;
@Autowired
private PercentageService percentageService;
@Autowired
private ExerciseService exerciseService;



@RequestMapping("/")
@SuppressWarnings("unchecked")
public String showWorkout(Long id, Model model,Workout workout){





    Workout firstWorkout = workoutService.findById(Long.valueOf(83));

    model.addAttribute("firstWorkout",firstWorkout);
    model.addAttribute("workout",workout);

    return "workout";
}

@RequestMapping(value="/workoutLogs", method = RequestMethod.POST)
public String saveWorkout(@ModelAttribute Workout workout,Model model) {


    workoutService.saveNewWorkout(workout);


    return "redirect:/workoutLogs";
}


@RequestMapping("/workoutLogs")
public String showAllSavedWorkoutLogs(Model model){


    return "WorkoutLogs";

}



}

锻炼道:

@Repository
public class WorkoutDaoImpl implements WorkoutDao {

@Autowired
SessionFactory sessionFactory;

@Override
@SuppressWarnings("unchecked")
public List<Workout> findAll() {
    Session session = sessionFactory.openSession();
    List<Workout> workouts = session.createCriteria(Workout.class).list();
    session.close();
    return workouts;
}

@Override
public Workout getFirstWorkoutExerciseName(Long id) {
    return null;
}

@Override
public Workout getWorkout() {
    return null;


}


@Override
public Workout findById(Long id) {
    Session session = sessionFactory.openSession();
    Workout workout = session.get(Workout.class,id);
    Hibernate.initialize(Workout.class);
    return workout;
}


@Override
public void save(Workout workout) {
    Session session = sessionFactory.openSession();

    // Begin a transaction
    session.beginTransaction();

    // Save the category
    session.saveOrUpdate(workout);

    // Commit the transaction
    session.getTransaction().commit();

    // Close the session
    session.close();
}

@Override
public void delete(Workout workout) {

}


}

【问题讨论】:

  • 您手动编写这些 DAO 而不是使用 Spring Data 自动生成它们有什么特别的原因吗?
  • 没有什么特别的原因,这只是我被教导的方式,我没有将弹簧数据添加到我的项目中。我正在使用 Spring Boot。

标签: java hibernate spring-boot mapping


【解决方案1】:

使用mappedBy 进行双向关联,不要在关联的每一侧使用@JoinColumn (what is @JoinColumn and how it is used in Hibernate)。

@OneToMany(mappedBy = "workout", cascade = CascadeType.ALL)
private List<Exercise> exercises;

@ManyToOne
@JoinColumn(name = "workout_id")
private Workout workout;

如果要在不属于Workout 时删除Exercise 行,请使用orphanRemoval = true

@OneToMany(mappedBy = "workout", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Exercise> exercises;

从数据库更新Workout

  1. 从数据库中获取Workout
  2. exercises 集合中更新一些Exercise
  3. 更新/合并Workout

从数据库更新exercises

您可以通过Workout id 获得一组练习(没有Workout)。并更新其中的任何一个和saveOrUpdate 每个。

根据请求更新Workout

您应该在Workout 中有id。此外,每个具有现有 idExercise 都将被更新(并且将使用不存在的 id 创建,至少对于 Hibernate 4.11),每个没有 ID 的 Exercise 都将被创建,每个 exercises 集合中都不存在Exercise 将与 orphanRemoval = true 一起删除。

在这种情况下始终使用merge()saveOrUpdate() 将不起作用(至少不会删除练习)。

这是一个错误的方法:

@Override
public Workout findById(Long id) {
    Session session = sessionFactory.openSession();
    Workout workout = session.get(Workout.class,id);
    Hibernate.initialize(Workout.class);
    return workout;
}

你需要关闭一个会话,这是垃圾Hibernate.initialize(Workout.class)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    • 2019-03-12
    • 1970-01-01
    • 2015-02-02
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    相关资源
    最近更新 更多