Как обновить сущность с помощью spring-data-jpa?
ну вопрос в значительной степени говорит все. Использование JPARepository как обновить сущность?
JPARepository имеет только сохранить метод, который не говорит мне, если это создать или обновить на самом деле. Например, я вставляю простой объект в базу данных пользователя, который имеет три поля: firstname и lastname и age:
@Entity
public class User {
private String firstname;
private String lastname;
//Setters and getters for age omitted, but they are the same as with firstname and lastname.
private int age;
@Column
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
@Column
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
private long userId;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public long getUserId(){
return this.userId;
}
public void setUserId(long userId){
this.userId = userId;
}
}
тогда я просто "сохраняю", что на данный момент является вставкой на самом деле:
User user1 = new User();
user1.setFirstname("john"); user1.setLastname("dew");
user1.setAge(16);
userService.saveUser(user1);// This call is actually using the JPARepository: userRepository.save(user);
ок все хорошо. Теперь я хочу чтобы обновить этого пользователя, скажем, изменить его возраст. Ну, я мог бы использовать запрос для этого либо QueryDSL, либо NamedQuery, что угодно. Но, учитывая, что я просто хочу использовать spring-data-jpa и JPARepository, как мне сказать, что вместо вставки я хочу сделать обновление?
в частности, как я могу сказать spring-data-jpa, что пользователи с одинаковым именем пользователя и именем пользователя фактически равны и что предполагается обновить сущность. Переопределение равных не сработало.
спасибо Ты!
5 ответов:
идентичность объектов определяется их первичными ключами. Так как
firstnameиlastnameне являются частями первичного ключа, вы не можете сказать JPA лечитьUsers с тем жеfirstnames иlastnameы как равные, если они имеют разныеuserIds.Итак, если вы хотите обновить
Userопределить по егоfirstnameиlastname, вам необходимо найтиUserС помощью запроса, а затем изменить соответствующие поля объекта, который вы нашли. Эти изменения будут сброшены в базу данных автоматически в конце транзакции, так что вам не нужно ничего делать, чтобы сохранить эти изменения явно.EDIT:
возможно, я должен подробно остановиться на общей семантике JPA. Существует два основных подхода к проектированию API персистентности:
вставить / обновить подход. Когда вам нужно изменить базу данных, вы должны вызвать методы persistence API явно: вы вызываете
insertвставить объект, илиupdateдля сохранения нового состояния объекта в базе данных.единица подход к работе. В этом случае у вас есть набор объектов управлял библиотека настойчивость. Все изменения, которые вы вносите в эти объекты, будут автоматически сброшены в базу данных в конце единицы работы (т. е. в конце текущей транзакции в типичном случае). Когда вам нужно вставить новую запись в базу данных, вы делаете соответствующий объект управлял. управлял объекты идентифицируются по их первичным ключам, так что если вы создадите объект с предопределенным первичным ключом управлял, он будет связан с записью базы данных того же идентификатора, и состояние этого объекта будет автоматически распространяться на эту запись.
JPA следует более позднему подходу.
save()весной данные JPA поддерживаютсяmerge()в простом JPA, поэтому он делает вашу сущность управлял как описано выше. Это значит, что вызовsave()на объекте с предопределенным идентификатором будет обновляться соответствующая запись базы данных, а не вставлять новую, а также объясняет, почемуsave()это не называетсяcreate().
так как ответ @axtavt фокусируется на
JPAнеspring-data-jpaчтобы обновить объект путем запроса, сохранение не эффективно, потому что для этого требуется два запроса, и, возможно, запрос может быть довольно дорогим, поскольку он может присоединяться к другим таблицам и загружать любые коллекции, которые имеют
fetchType=FetchType.EAGER
Spring-data-jpaподдерживает операции обновления.
Вы должны определить метод в интерфейсе репозитория.и аннотировал его с@Queryи@Modifying.@Modifying @Query("update User u set u.firstname = ?1, u.lastname = ?2 where u.id = ?3") void setUserInfoById(String firstname, String lastname, Integer userId);
@Queryпредназначен для определения пользовательского запроса и@Modifyingэто для того, чтобы сказатьspring-data-jpaчто этот запрос является операцией обновления, и оно требуетexecuteUpdate()неexecuteQuery().
использование spring-data-JPA save(), У меня была та же проблема, что и @DtechNet. Я имею в виду, что каждый save() создавал новый объект вместо обновления. Чтобы решить эту проблему, мне пришлось добавить "версию", поданную в entity и связанную таблицу.
вот как я решил проблему:
User inbound = ... User existing = userRepository.findByFirstname(inbound.getFirstname()); if(existing != null) inbound.setId(existing.getId()); userRepository.save(inbound);
вы можете просто использовать эту функцию с Save() JPAfunction, но объект отправлены в качестве параметра должно содержать существующий ID в базе данных, в противном случае он не будет работать, потому что Save() когда мы посылаем объекта без документов, он добавляет непосредственно строку в базе данных, но если мы посылаем объект с существующим кодом, он меняет столбцы в базе данных.
public void adduser(Userinfos u) { User userFromDb = userRepository.findById(u.getid()); //crush the variables of the object found userFromDb.setFirstname("john"); userFromDb.setLastname("dew"); userFromDb.setAge(16); userRepository.save(userFromDb); }