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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22031128/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 13:09:31  来源:igfitidea点击:

how to update an entity with spring data jpa

javaspringhibernatejpa

提问by nspessot

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

提前致谢

回答by Koitoer

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.

这意味着应用程序上下文也需要再次生成 bean,所以请确保您在 persistence.xml 中的配置没有设置 h2bml 来创建。还可以考虑在您的服务中调用 flush 方法。

回答by chinesewhiteboi

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,

您当前所做的就是保存一个人。这就是它创建第二个条目的原因。
你应该做的是先找到老人,

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

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

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

回答by ciri-cuervo

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

回答by Venkata Santhosh Piduri

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