Как обновить объект с помощью spring данных jpa

У меня есть сущность и Junit, я хочу проверить, что метод обновления работает нормально, но когда я вызываю метод сохранения из CrudRepository, я получаю новую запись в своей таблице вместо обновленного объекта.

Это моя сущность:

@Entity(name = "PERSON")
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "PERSON_ID")
    private Integer id;
    @Column(name = "FIRST_NAME")
    private String firstName;
    @Column(name = "LAST_NAME")
    private String lastName;
//getters and setters
}

Это мой класс обслуживания:

@Service
public class PersonServiceImpl implements PersonService {

    @Autowired
    private PersonRepository personRepository;

    @Override
    public Person updatePerson(Person oldPerson) throws Exception { 

        return personRepository.save(oldPerson);
    }
}

Это мое хранилище

public interface PersonRepository extends CrudRepository<Person, String> {
}

Это мой тест:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { JPAConfigurationTest.class })
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
@Transactional
public class UpdatePersonServiceIntegrationTest {
        @Autowired
    PersonService personService;

        @Before
    public void setUp() throws Exception {
        Person person = new Person(1);
        person.setFirstName("Nicolas");
        person.setLastName("Spessot");

        personService.createPerson(person); //This invokes save
    }

        @Test
    public void updatingPerson() throws Exception{
        Person person = new Person(1);
        person.setFirstName("Juan");
        person.setLastName("Riquelme");

        personService.updatePerson(person);

        Person retrieved = personService.retrievePerson(1); //This invokes findOne

        assertEquals(1, person.getId());
        assertEquals("Juan", person.getFirstName());
        assertEquals("Riquelme", person.getLastName());
    }
}

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

Ответ 1

Проблема заключается в вашем методе updatePerson в вашем классе обслуживания. В частности:

return personRepository.save(oldPerson);

Все, что вы сейчас делаете, это сохранение Person. Вот почему он создает вторую запись.
Что вам нужно сделать, это сначала найти oldPerson,

Person p = personRepository.findOne(oldPerson.getId())

затем обновите его атрибуты, а затем сохраните их, как и раньше. Надеюсь, что это поможет.

Ответ 2

Вы должны реализовать equals() и hashCode() в классе Person.

@Entity(name = "PERSON")
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "PERSON_ID")
    private Integer id;
    @Column(name = "FIRST_NAME")
    private String firstName;
    @Column(name = "LAST_NAME")
    private String lastName;
    //getters and setters

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (id == null || obj == null || getClass() != obj.getClass())
            return false;
        Person that = (Person) obj;
        return id.equals(that.id);
    }
    @Override
    public int hashCode() {
        return id == null ? 0 : id.hashCode();
    }
}

Ответ 3

Я думаю, что репозиторий должен быть

public interface PersonRepository extends CrudRepository<Person, Integer> {

Поскольку ваш Id является Integer not String, также я предполагаю, что ваш

personService.createPerson(person); 

Внутренне использовать метод сохранения репо.

Моим вторым советом является

@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)}

Это означает, что контекст приложения нужно снова создать снова beans, поэтому, пожалуйста, убедитесь, что ваша конфигурация в файле persistence.xml не имеет установленного h2bml. Также рассмотрите способ вызова flush в вашем сервисе.

Ответ 4

Два способа сделать эту работу

переопределить метод compareTo как

@Entity(name = "PERSON")
public class Person implements Comparable<Person>{
 //... all your attributes goes here
 private Integer id;

 @Override
public int compareTo(Person person) {
   return this.getId().compareTo(person.getId());
}} 

или

вам необходимо переопределить методы equals и hashcode в классе сущности, как показано ниже

 @Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (id == null || obj == null || getClass() != obj.getClass())
        return false;
    Person that = (Person) obj;
    return id.equals(that.id);
}
@Override
public int hashCode() {
    return id == null ? 0 : id.hashCode();
}