简体   繁体   English

如何使用 spring 数据 jpa 更新实体

[英]how to update an entity with spring data jpa

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,我想测试 update 方法是否工作正常,但是当我从 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提前致谢

The problem is in your updatePerson method in your service class.问题出在服务类中的 updatePerson 方法中。 Specifically:具体来说:

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,你应该做的是先找到老人,

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

then update its attributes, and then save it like you did before.然后更新它的属性,然后像以前一样保存它。 Hope that helps.希望有帮助。

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

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.这意味着应用程序上下文也需要再次生成 bean,所以请确保您在 persistence.xml 中的配置没有设置 h2bml 来创建。 Also consider to call flush method in your service.还可以考虑在您的服务中调用 flush 方法。

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

One doesn't have to do any complex operations for this.无需为此进行任何复杂的操作。 In your service class you can do something like this.在你的服务类中,你可以做这样的事情。

 @Service
public class PersonServiceImpl implements PersonService {

    @Autowired
    private PersonRepository personRepository;

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

      oldPerson.setId(oldPerson.getId()) ; // pass the associated id for which you want to update and set that id to the same person [ basically setting the same id to the oldPerson ] this way it will not create new entry because here we are not making new ID ] 

 //oldPerson.set others [ what is to be updated ]  


        return personRepository.save(oldPerson); // now save [old person with updated content but same id as it was before ]
    }
}

This solves the problem of creating new entry to the database and updates the same content with Id associate with that person.这解决了在数据库中创建新条目的问题,并使用与该人关联的 Id 更新相同的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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