web-dev-qa-db-fra.com

comment mettre à jour une entité avec Spring Data JPA

J'ai une entité et un Junit, je veux tester que la méthode de mise à jour fonctionne correctement, mais lorsque j'appelle la méthode save depuis CrudRepository, je reçois une nouvelle entrée dans ma table au lieu de l'entité mise à jour.

Ceci est mon entité:

@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
}

Ceci est ma classe de service:

@Service
public class PersonServiceImpl implements PersonService {

    @Autowired
    private PersonRepository personRepository;

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

        return personRepository.save(oldPerson);
    }
}

Ceci est mon référentiel

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

Ceci est mon test:

@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());
    }
}

Merci d'avance

16
nspessot

Le problème provient de votre méthode updatePerson dans votre classe de service. Plus précisément:

return personRepository.save(oldPerson);

Tout ce que vous faites actuellement est de sauvegarder une personne. C'est pourquoi il crée une deuxième entrée.
Ce que vous devez faire est de trouver oldPerson en premier, 

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

puis mettez à jour ses attributs, puis enregistrez-le comme vous l'avez fait auparavant . J'espère que cela vous aidera.

25
chinesewhiteboi

Vous devez implémenter equals() et hashCode() dans la classe 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();
    }
}
5
ciri-cuervo

Je pense que le référentiel devrait être

public interface PersonRepository extends CrudRepository<Person, Integer> {

Comme votre identifiant est Integer pas String, je suppose aussi que votre

personService.createPerson(person); 

Utilisez en interne la méthode save du repo.

Mon deuxième conseil est le 

@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)}

Cela signifie que le contexte de l'application doit être généré à nouveau, ainsi que des beans, assurez-vous donc que votre configuration dans persistence.xml ne dispose pas du paramètre h2bml pour créer . Pensez également à appeler la méthode flush dans votre service.

1
Koitoer

Deux façons de faire ce travail

remplacer la méthode compareTo comme 

@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());
}} 

ou 

vous devez redéfinir les méthodes equals et hashcode dans votre classe d'entité, comme indiqué ci-dessous 

 @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();
}