[SPRING] JPA에서 Spring MVC를 사용하여 엔티티의 속성 하위 집합 만 업데이트 할 수 있습니까?
SPRINGJPA에서 Spring MVC를 사용하여 엔티티의 속성 하위 집합 만 업데이트 할 수 있습니까?
Spring Roo에서 Spring MVC와 JPA를 사용하여 MySQL 데이터베이스에서 지속성을 유지하려고합니다. 저는 Spring MVC와 Java에 대해 매우 익숙하지만 CakePHP와 Rails를 사용해 왔습니다.
암호와 함께 개인 정보가 포함 된 User 엔티티가 있습니다. 다음과 같은 것 (추가 .aj 파일에서 Roo가 생성 한 많은 기능 제외) :
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private Long id;
@Column(name = "PASSWORD", length = 32)
private String password;
@Column(name = "FIRST_NAME", length = 25)
private String firstName;
@Column(name = "LAST_NAME", length = 25)
private String lastName;
@Column(name = "ADDRESS", length = 255)
private String address;
// The appropriate getters and setters
...
}
그런 다음 사용자 컨트롤러에서 Roo의 자동 생성 스 캐 폴딩 규칙에 따라 만든 편집 동작이 있습니다.
@RequestMapping(value="/edit", method = RequestMethod.GET)
public String editForm(Model uiModel) {
String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
uiModel.addAttribute("user", User.findUserByUsername(username).getSingleResult());
return "account/edit";
}
그리고 Roo의 규칙을 다시 따르는 JSPX 뷰는 폼을 렌더링한다.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:field="urn:jsptagdir:/WEB-INF/tags/form/fields" xmlns:form="urn:jsptagdir:/WEB-INF/tags/form" xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
<jsp:directive.page contentType="text/html;charset=UTF-8"/>
<jsp:output omit-xml-declaration="yes"/>
<form:update id="" label="Personal Details" modelAttribute="user" path="/account" versionField="none">
<field:input id="" field="firstName" label="First Name" />
<field:input id="" field="lastName" label="Last Name" />
<field:textarea id="" field="address" label="Street Address" />
</form:update>
</div>
양식에서 암호, 단지 제공된 필드 (이름, 성 및 주소) 만 업데이트하도록하지는 않습니다.
Roo 관례에 따라 업데이트 작업 :
@RequestMapping(method = RequestMethod.PUT, produces = "text/html")
public String edit(@Valid User user, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
if (bindingResult.hasErrors()) {
uiModel.addAttribute("user", user);
return "account/edit";
}
uiModel.asMap().clear();
user.merge();
return "redirect:/account";
}
사용자 객체는 완벽하게 업데이트되지만 양식의 입력으로 제공되지 않아 양식 제출 요청 처리기로 전달 된 User 객체에서 null로 설정되므로 암호 필드를 null로 덮어 쓰는 것이 문제입니다. Roo가 생성 한 스캐 폴딩에서는 모든 열에 대해 양식 입력을 제공하기 때문에 문제가 나타나지 않습니다. 그래서 그것을 숨겨진 필드로 추가 할 수는 있지만 좋은 생각처럼 들리지는 않습니다. 그리고 나는 그것을하는 훨씬 더 좋은 방법이 있다는 느낌을 얻습니다 ...
다시 말해, Spring / JPA가 SQL을 생성하게하는 방법은 무엇입니까?
UPDATE user SET firstname=?, lastname=?, address=?
대신에
UPDATE user SET firstname=?, lastname=?, address=?, password=?
내가이 모든 것을 처음 접했기 때문에 코드 샘플이 환상적 일 것입니다. :)
고맙습니다!
업데이트 : 나는 그것을 사용자 모델에 다음 메소드를 추가하여 yglodt의 제안을 사용하여 작동하게 만들 수있었습니다.
@Transactional
public void mergeWithExistingAndUpdate() {
final User existingUser = User.findUser(this.getId());
existingUser.setFirstName(this.getFirstName());
existingUser.setLastName(this.getLastName());
existingUser.setAddress(this.getAddress());
existingUser.flush();
}
user.merge () 대신 내 컨트롤러 액션에서 호출 :
user.mergeWithExistingAndUpdate();
해결법
-
==============================
1.나는 보통 이것을 서비스 계층에서 해결한다.
나는 보통 이것을 서비스 계층에서 해결한다.
DB에서 갱신하려는 엔티티를 읽고 양식에서 가져 오는 속성을 겹쳐 쓸 수 있습니다.
이렇게하면 원하는 속성 만 변경할 수 있습니다.
코드 예 :
@Service @Transactional public class UserService { @Resource(name = "sessionFactory") private SessionFactory sessionFactory; public void mergeWithExistingAndUpdate(final Person personFromPost) { Session session = sessionFactory.getCurrentSession(); Person existingPerson = (Person) session.get(Person.class, personFromPost.getId()); // set here explicitly what must/can be overwritten by the html form POST existingPerson.setName(personFromPost.getName()); existingPerson.setEmail(personFromPost.getEmail()); existingPerson.setDateModified(new Date()); existingPerson.setUserModified(Utils.getCurrentUser()); session.update(existingPerson); } }
1 편집
실제로이 문제를 해결할 Spring 방식이 있습니다. @SessionAttributes를 사용하면이 anwer를 볼 수 있습니다.
https://stackoverflow.com/a/3675919/272180
아직 테스트하지는 않았지만 유망 해 보입니다.
EDIT 2
결국 나는 그것을 테스트하고 예상대로 작동합니다.
그러나 발로 쏘을 수있는 한 가지가 있습니다.
같은 양식으로 여러 탭을 열면 마지막 탭의 여는 부분은 다른 탭의 sessionAttribute를 덮어 쓰며 제출할 때 잠재적으로 데이터가 손상 될 수 있습니다. 이 블로그 게시물에 해결 방법이 있습니다. http://marty-java-dev.blogspot.com/2010/09/spring-3-session-level-model-attributes.html
그러나 결국 편집을 위해 여러 개의 탭을 열지 않으면 어쨌든 문제가 발생하지 않습니다.
-
==============================
2.이 기사에서는 귀하의 질문에 대해 자세히 설명하지만, 여기에서도 요약 해 보겠습니다.
이 기사에서는 귀하의 질문에 대해 자세히 설명하지만, 여기에서도 요약 해 보겠습니다.
특정 속성을 업데이트하지 않으려면 updatable = false로 표시 할 수 있습니다.
@Column(name="CREATED_ON", updatable=false) private Date createdOn;
현재 Session이나 EntityManager가 열려있는 한 엔티티를로드하고 수정하면 Hibernate는 더티 확인 메커니즘을 통해 변경 사항을 추적 할 수 있습니다. 그런 다음 플러시하는 동안 SQL 업데이트가 실행됩니다.
모든 열이 UPDATE 문에 포함되는 것이 마음에 들지 않으면 동적 업데이트를 사용할 수 있습니다.
@Entity @DynamicUpdate public class Product { //code omitted for brevity }
그런 다음 수정 된 열만 UPDATE 문에 포함됩니다.
-
==============================
3.퍼시스턴스 프로 바이더가 Hibernate 인 경우 엔티티에서 최대 절전 모드 별 주석을 사용하십시오 : @DynamicUpdate :
퍼시스턴스 프로 바이더가 Hibernate 인 경우 엔티티에서 최대 절전 모드 별 주석을 사용하십시오 : @DynamicUpdate :
from https://stackoverflow.com/questions/14699087/is-it-possible-to-update-only-a-subset-of-attributes-on-an-entity-using-spring-m by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring 속성 place holder를 사용하여 파일 .properties에서 목록 읽기 (0) | 2019.02.01 |
---|---|
[SPRING] 스프링 프로토 타입 범위를 사용해야 할 때? (0) | 2019.02.01 |
[SPRING] 동일한 스프링 빈을 같은 이름으로 두 번 정의하기 (0) | 2019.02.01 |
[SPRING] UsernamePasswordAuthenticationToken에 대한 AuthenticationProvider가 없습니다. (0) | 2019.02.01 |
[SPRING] Spring 용 webflux 사용자 정의 인증 (0) | 2019.02.01 |