如何使用spring data jpa更新实体

时间:2022-09-11 16:06:13

I have an entity and a Junit, I want to test that update method is working fine, but when I invoke save method from CrudRepository I get a new entry in my table instead of the updated entity.

我有一个实体和一个Junit,我想测试更新方法工作正常,但是当我从CrudRepository调用save方法时,我在我的表中获得了一个新条目,而不是更新的实体。

This is my entity:

这是我的实体:

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

This is my service class:

这是我的服务类:

@Service
public class PersonServiceImpl implements PersonService {

    @Autowired
    private PersonRepository personRepository;

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

        return personRepository.save(oldPerson);
    }
}

This is my repository

这是我的存储库

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

This is my 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());
    }
}

Thanks in advance

提前致谢

4 个解决方案

#1


24  

The problem is in your updatePerson method in your service class. Specifically:

问题出在您的服务类中的updatePerson方法中。特别:

return personRepository.save(oldPerson);

All you are currently doing is saving a Person. That's why it is creating a second entry.
What you should do is find the oldPerson first,

你目前正在做的就是拯救一个人。这就是它创建第二个条目的原因。你应该做的是先找到oldPerson,

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

then update its attributes, and then save it like you did before. Hope that helps.

然后更新其属性,然后像以前一样保存它。希望有所帮助。

#2


5  

You must implement equals() and hashCode() in class Person.

您必须在Person类中实现equals()和hashCode()。

@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


1  

I think the repository should be

我认为存储库应该是

public interface PersonRepository extends CrudRepository<Person, Integer> {

As your Id is Integer not String, also I assume that your

由于你的Id是整数而不是字符串,我也认为你的

personService.createPerson(person); 

Internally use save method of the repo.

内部使用repo的save方法。

My second advice is the

我的第二个建议是

@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)}

This mean that the app Context need to be generated again also beans, so please be sure that your configuration in persistence.xml is not having h2bml set to create. Also consider to call flush method in your service.

这意味着还需要再次生成应用程序上下文,因此请确保您在persistence.xml中的配置没有将h2bml设置为create。还要考虑在您的服务中调用flush方法。

#4


0  

Two ways to make this work

两种方法使这项工作

override compareTo method as

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

or

要么

you need to override equals and hashcode methods in your entity class as below

您需要在实体类中重写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();
}

#1


24  

The problem is in your updatePerson method in your service class. Specifically:

问题出在您的服务类中的updatePerson方法中。特别:

return personRepository.save(oldPerson);

All you are currently doing is saving a Person. That's why it is creating a second entry.
What you should do is find the oldPerson first,

你目前正在做的就是拯救一个人。这就是它创建第二个条目的原因。你应该做的是先找到oldPerson,

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

then update its attributes, and then save it like you did before. Hope that helps.

然后更新其属性,然后像以前一样保存它。希望有所帮助。

#2


5  

You must implement equals() and hashCode() in class Person.

您必须在Person类中实现equals()和hashCode()。

@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


1  

I think the repository should be

我认为存储库应该是

public interface PersonRepository extends CrudRepository<Person, Integer> {

As your Id is Integer not String, also I assume that your

由于你的Id是整数而不是字符串,我也认为你的

personService.createPerson(person); 

Internally use save method of the repo.

内部使用repo的save方法。

My second advice is the

我的第二个建议是

@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)}

This mean that the app Context need to be generated again also beans, so please be sure that your configuration in persistence.xml is not having h2bml set to create. Also consider to call flush method in your service.

这意味着还需要再次生成应用程序上下文,因此请确保您在persistence.xml中的配置没有将h2bml设置为create。还要考虑在您的服务中调用flush方法。

#4


0  

Two ways to make this work

两种方法使这项工作

override compareTo method as

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

or

要么

you need to override equals and hashcode methods in your entity class as below

您需要在实体类中重写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();
}