如何使用spring data jpa更新实体

时间:2014-02-26 03:29:15

标签: java spring hibernate jpa

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

这是我的实体:

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

提前致谢

5 个答案:

答案 0 :(得分:27)

问题在于服务类中的updatePerson方法。具体做法是:

return personRepository.save(oldPerson);

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

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

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

答案 1 :(得分:5)

您必须在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();
    }
}

答案 2 :(得分:1)

我认为存储库应该是

public interface PersonRepository extends CrudRepository<Person, Integer> {

由于你的Id是整数而不是字符串,我还假设你的

personService.createPerson(person); 

内部使用回购的保存方法。

我的第二个建议是

@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)}

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

答案 3 :(得分:0)

使这项工作的两种方法

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

答案 4 :(得分:0)

无需为此执行任何复杂的操作。 在您的服务类中,您可以执行以下操作。

<script>
    $('#workshops').on('hide.bs.modal', function () {
        stopVideo("resp-iframe");
    });
</script>

这解决了在数据库中创建新条目并使用与该人相关联的ID更新相同内容的问题。