Как обновить сущность с помощью 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 лечитьUser
s с тем жеfirstname
s иlastname
ы как равные, если они имеют разныеuserId
s.Итак, если вы хотите обновить
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); }