지금은 2개의 테이블이지만 생성/수정일을 몇십개의 테이블에 다 넣어야한다면, 저짓을 겁나많이해야된다.
너무귀찮은일임.
@Enttiy
public class Company {
@Id @GeneratedValue
private Long id;
private String name;
private String address;
private LocalDateTime createdDate;
private String createdBy;
private LocalDateTime updatedDate;
private String updatedBy;
}
@Entity
public class User {
@Id @GeneratedValue
private Long userId;
private String name;
private String mobile;
private String email;
private LocalDateTime createdDate;
private String createdBy;
private LocalDateTime updatedDate;
private String updatedBy;
}
보기만 해도 토가나온다.
이것을 안하기위해서 MappedSuperClass 를 써보자
BaseEntity 라는 이름을 써서 만들어줄것임
@MappedSuperClass
public abstract class BaseEntity {
private LocalDateTime createdDate;
private String createdBy;
private LocalDateTime updatedDate;
private String updatedBy;
}
주의할점은 abstract 로 작성해야된다는점임.
이제 이것을 붙여보면
@Enttiy
public class Company extends BaseEntity {
@Id @GeneratedValue
private Long id;
private String name;
private String address;
}
@Entity
public class User extends BaseEntity {
@Id @GeneratedValue
private Long userId;
private String name;
private String mobile;
private String email;
}
짠~
가독성으로만 따져봐도 중요한 변수만 보임!
근데 사이트가 커져서, 회사를 업종별로 select 하고싶어졌다...
별도로 관리를 해줘야한다면? company를 업종별로 나눠야겠지
근데, 어짜피 이름 주소 ...등등 기본적인건 다 쓰니까 그대로두고
업종 + 업종별 unique 컬럼들만 쏙쏙 빼서 관리하고싶다면???
2.@inherited & @DiscriminatorColumn
company 에 pk로 company_id 넣어주고
dtype 이라는 컬럼으로 자식들 구분값 fk로 넣어주는식으로 해야 나중에 select 해올때 dtype 값으로 join 해서 가져오겠지.
이것을 JPA로 구현해보자
일단 기본이 되는 COMPANY 를 생성
@Enttiy
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public class Company extends BaseEntity {
@Id @GeneratedValue
@Column(name = "COMPANY_ID")
private Long id;
private String name;
private String address;
}
새로보는 애노테이션이 있쥬??
@Inheritance 의 InheritanceType 전략에 따라 다양한 테이블을 만들수있음.
지금만드려는건 join 형태의 테이블이니까 JOIN을 쓰지만, SINGLE_TABLE, TABLE_PER_CLASS 전략이 있는데
다른애들은 테이블통째로 만들어서 별로다.
@Inheritance 로 전략을 설정하고
@DiscriminatorColumn으로 부모가 누군지 알려준다. 나대지 못하도록.
글고 부모테이블 (company)에 자식들 구분값을 넣어주는 컬럼을 생성해준다.
DTYPE 이라는 이름으로 자동값으로 생성되는데 이름을 바꿔줘도되지만, 보통은 이걸로 쓰는거같다.
그리고 자식을 만들어주자
@Entity
@DiscriminatorValue("O")
public class Office extends Company {
@Id @GeneratedValue
private Long officeId;
private String businessType;
private String ceo;
}
@Entity
@DiscriminatorValue("S")
public class Store extends Company {
@Id @GeneratedValue
private Long storeId;
private String businessType;
private String cto;
}
@Entity
@DiscriminatorValue("R")
public class Restorant extends Company {
@Id @GeneratedValue
private Long restorantId;
private String businessType;
private String chef;
}
자식은 테이블 따로만들꺼니까 @Entity 달아주고
자식에겐 이름을 지어줘야지.
@DiscriminatorValue 로 이름을 지어준다.
이렇게하면 부모의 DTYPE 컬럼에 discriminatorValue로 설정한 문자들이 박히게된다.
자 여기까지 하면 상속은 왠만한건 다 끝난것같지만? 갑자기 이런녀석도있다.
3. @Embedded
이녀석도 상속하는녀석인데... 대체 님 뭐임?
@MapperSuperClass 형님 어쩔깝쇼??
일단 형님의 특징은 아래와같다.
@Entity 로 선언된 엔티티 클래스는 같은 엔티티클래스 혹은 @MapperSuperClass 로 지정된 클래스만 상속이 가능하다.
형님은 부모클래스는 자식클래스에 매핑정보만 제공하는 역할이다.
또한 단독으로 사용되는 일이 없으므로 추상클래스로 사용하는게 좋고
전체 엔티티에서 공통으로 적용하는 정보를 모을때 사용한다
그럼 샛병아리 @Embedded 는?
@Getter @Setter
@Embeddable
public class Times {
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
}
일단 냅다 만들고
전 쓰여지는 애입니다~ 하는 Embeddable 애노테이션을 달아준다.
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
@Embedded
private Times times;
}
그리고 쓰는곳에서 변수중에 임베디드 할 녀석을 지정해준다.
이렇게되면 @MappedSuperClass 성님처럼 부모노릇은 못하고 노예처럼 사용되게된다 후후
jsp단에서 java로 배열 array 전송 시 java.lang.NumberFormatException: For input string: "" 에러가 발생했다.
나의 경우
1. jsp에서 java 로 ajax 전송
var param = {
"id" :"123",
"isIssue" : "Y"
};
$.post('/경로', param, function(response){
if (response.isSuccess) alert("성공);
});
2. 그리고 java 컨트롤러에서 잘 들어왔는지 확인 후 처리
@RequestMapping(value="/경로")
@ResponseBody
public JsonView codeCheck(TaxInvoice invoice) {
//처리
}
들어올때 TaxInvoice 라는 dto 형식으로 들어오게되는데 해당 dto는 아래와 같다.
3. dto 형식
public class TaxInvoice {
private String[] id;
private String isIssue;
}
문제는 dto의 id를 보면 string[] array로 되어있었고 나는 파라미터를 보낼때 배열을 보내고싶었다.
var param = {
"id" :["123","123"],
"isIssue" : "Y"
};
그래서 위와같이 배열을 만들어서 넣어줬지만, 통하지 않았고 익셉션발생.
java.lang.NumberFormatException: For input string: "" (AbstractHandlerExceptionResolver.java : 133) *****
[07/27 10:56:32] OP-210727105632485-/opmanager/receipt/tax-invoice/update-status [AJAX] ERROR 1 - - - ***** [예외발생] {} (OpHandlerExceptionResolver.java : 76) *****
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:592)
at java.lang.Integer.parseInt(Integer.java:615)
at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:327)
at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:280)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:95)
at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:834)
at org.springframework.validation.DataBinder.doBind(DataBinder.java:730)
at org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:189)
at org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:106)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.bindRequestParameters(ServletModelAttributeMethodProcessor.java:150)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:110)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:78)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
해결방법은 ajax post 옵션 설정에 있었다.
ajax 옵션 중 traditional : true를 추가해야 했었다.
축약형 $.post 형식으로 쓰고있어서 옵션을 예쁘게 넣는방법이 없나 고민했지만, 결국 풀어쓰기로했다.
var param = {
"id" :["123","123"],
"isIssue" : "Y"
};
$.ajax({
type : "post",
url : "/경로",
data : param,
traditional : true,
dataType : "json",
success: function (response){
alert("성공");
location.reload();
}
});