Skip to content

Java Bean

smarterp(vmerp)에서는 파라미터와 조회결과에 HashMap을 확장한 ErpMap을 사용했으나 smart-erp-lite에서는 파라미터와 조회결과에 JavaBean을 사용한다. 단순히 조회 결과를 return 할때 JavaBean에 없는 필드가 많을 경우 JavaBean 대신 CamelMap(resultType="camelMap")을 사용할 수 있다.

Java Bean은 클라이언트에서 요청하는 파리미터를 담아서 db에 저장 할때와 db에서 조회한 데이터를 담아서 클라이언트에 응답할때 사용한다. 클라이언트와 주고받는 데이터는 json형식 인데, Springframework이 Controller의 메소드의 파라미터에 맞춰서 json을 bean으로 변환해주고, 응답할때는 bean을 json으로 변환해준다.

기본 Bean은 insert, update, delete에 사용하는데, 필드는 db table의 컬럼으로만 구성하고 BaseModel을 상속한다. Bean의 이름은 table의 이름을 Pascal case로 작성한다.

postgresql에서는 map 사용시 sql에서 postgresql 문법의 형변환을 해줘야하는데, JavaBean을 사용하면 형변환을 하지 않아도 된다.

  • db에 저장할 bean은 BaseModel를 extends 한다.
  • 팝업프로그램의 조회조건 bean은 PopupBaseModel을 extends 한다.

공통 Bean Extends

BaseModel
테이블마다 등록수정에 관련된 공통 컬림이 있는데 이 컬럼들은 개별 java bean에는 작성하지 않고 공통 모델인 BaseModel을 extends 한다. BaseModel은 생성자에서 baseUserIdSecurityUtils.getUserId()로 로그인한 사용자의 아이디를 설정해준다. sql Mapper에서는 INSERT_USER_IDUPDATE_USER_ID 컬럼에 #{baseUserId}로 설정한다. 조회할때는 insertUserId, updateUserId필드가 사용된다.

저장할때는 그리드의 CollectionView에서 추가, 수정, 삭제 된 데이터의 배열을 서버로 전송한다. 서버에서는 파라미터로 Bean List 형식으로 받아서 Service에서 저장할때 각 Bean마다 추가, 수정, 삭제 플래그로 구분해서 insert, update, delete한다.

  • getTr()
    FlexGrid에서 데이터의 추가, 수정, 삭제 타입(TrackType). 추가는 "A", 수정은 "E", 삭제는 "R"
  • getSi()
    저장하는 데이터의 순서가 중요할때 그리드의 데이터 순서를 알 수 있다.
  // 저장할때 세션의 사용자 아이디
  private String baseUserId;
  // 조회한 사용자아이디 컬럼
  private String insertUserId;
  private LocalDateTime insertDatetime;
  private String updateUserId;
  private LocalDateTime updateDatetime;
  public Integer getSi();
  public TRACK getTr();

PopupBaseModel
팝업 프로그램의 조회 조건으로 사용할 Param bean은 팝업 처리를 위한 공통 컬럼을 가진 PopupBaseModel을 extends 한다.

  private String codeCol;
  private String code;
  private String nameCol;
  private String name;

변수명

DB 컬럼명은 _로 구분자로 하여 대문자로 작성되있는데, JavaBean에서는 이를 camel-case로 변환하여 작성한다.

타입

Oracle의 컬럼 데이터 타입은 대응하는 java의 data type으로 작성한다.

  • VARCHAR2, NVARCHAR2

    • String
  • CLOB, NCLOB

    • String
    • Map사용시 오류가 발생하면 mapper.xml에서 resultMap을 사용한다.
        <resultMap id="getListResult" type="erpMap">
          <result property="contTxt" column="CONT_TXT" jdbcType="CLOB" javaType="java.lang.String"/>
        </resultMap>
        <select id="selectLicNoticeList" resultMap="getListResult">
        </select>
      
  • NUMBER

    • 컬럼이 nullable하면 Integer나 Long과 같은 wrapper class로하고 not null이면 int, long으로 할 수 도 있다.
    • 자리수가 지정되 있지 않지만 약 10자리 이상이 예상되면 (ex. 금액컬럼)는 long으로 선언한다.
    • 소수점이 있으면 double 또는 Double로 선언한다.
    • 해당 bean을 사용해서 사칙연산을 할 경우에는 BigDecimal을 사용해야한다.
    • mybatis는 소수점 있는 숫자를 BigDecimal 로 return 한다.
    • java bigdecimal 사용이유
        DoubleSampleBean dsb = new DoubleSampleBean();
        BigDecimal bd1 = BigDecimal.valueOf(dsb.getDoubleNumber1());
        BigDecimal bd2 = BigDecimal.valueOf(dsb.getDoubleNumber2());
        bd1.add(bd2);       //덧셈(+) 
        bd1.subtract(bd2);  //뺄셈(-) 
        bd1.multiply(bd2);  //곱셈(*) 
        bd1.divider(bd2);   //나눗셈(/)
        bd1.remainder(bd2); //나머지(%)
      
  • DATE

    • 날짜만 있는 일자와 시간까지 있는 일시 컬럼은 모두 DATE 타입인데, java 에서는 해당 컬럼이 일자이면 LocalDate, 일시이면 LocalDatetime 클래스로 사용한다.
    • java.util.Date는 사용하지 않는다.
    • json으로 변환시 LocalDateyyyy-MM-dd, LocalDatetimeyyyy-MM-dd HH:mm:ss로 변환된다.(application.yml에서 설정)

Bean의 활용

  • Controller의 조회조건 등의 request parameter 값을 보관하는 Param 클래스 사용시 조회조건의 변수명이 같은 경우가 많으므로 기본 bean을 extends 하고, 변경되는 변수만 추가한다.

  • mapper.xml에서 조회결과를 담는 resultType 으로 사용한다.

  • 서비스에서 로직 처리중 생성한 데이터를 DB에 저장할때 사용한다.

  • 테이블에 존재하지 않는 명칭이나 기타 필드를 추가할 수 있다.

  • 특정 프로그램에서 사용할때 추가되는 필드가 많으면 기본 bean을 상속해서 생성한다. 추후 테이블 변경시 기본 bean만 수정 하기위함.

  • 객체생성 Lombok 참조

하나의 sql에서 여러개의 JavaBean 매핑하기

resultType으로 받을 JavaBean에서 매핑할 JavaBean을 변수로 가진다.

@Getter
@Setter
public class MultiJavaBean {
  private JavaBeanA jbA;
  private JavaBeanB jbB;
  private JavaBeanC jbC;
}

sql에서 alias에 "resultType의 필드.JavaBean의 필드" 형식으로 매핑시킨다.

SELECT A.AAA   AS "jbA.aaa", -- JavaBeanA의 aaa 필드
       B.BBB   AS "jbA.bbb", -- JavaBeanB의 bbb 필드
       C.CCC   AS "jbA.ccc"  -- JavaBeanC의 ccc 필드
  FROM JAVA_BEAN_A A,
       JAVA_BEAN_B B,
       JAVA_BEAN_C C

MYBATIS_LITE View

Oracle의 view인 MYBATIS_LITE를 조회해서 VO_FIELD 컬럼의 값을 복사해서 이클립스의 업무 모듈별 model 패키지에 붙여넣기 한다.

TIP

java source를 복사해서 이클립스에서 붙여넣기하면 java파일이 해당 패키지에 생성된다.

mapper.xml 생성용 조회쿼리

SELECT *
FROM MYBATIS_LITE
WHERE TABLE_NAME = '테이블명(대문자)';

Example

package com.vmerp.sample.bean;

// Lombok 사용
@Getter
@Setter
@ToString(callSuper = true)
@SuperBuilder
@NoArgsConstructor

// 모든 Bean은 BaseModel을 extends 한다.
public class FormGrid extends BaseModel {

  /** VARCHAR2, NVARCHAR2, CLOB, NCLOB */
  private String string;

  /** DATE. 실제 값이 날짜만 저장 */
  private LocalDate dateDt;
  /** DATE. 실제 값이 시간까지 저장 */
  private LocalDateTime dateDatetime;

  /** 숫자의 범위가 -2,147,483,648 ~ 2,147,483,647 이면 Integer 또는 int */
  private Integer numberInt;
  /** 숫자의 범위가 2,147,483,647 보다 크거나 금액이면 Long 또는 long */
  private Long numberAmt;

  /** 숫자 소수점 있음. double, float, Double, Float은 가급적 사용말기를 */
  private BigDecimal numberPoint;
}
  • BaseModel
package com.vmerp.common.model;

import java.time.LocalDateTime;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.vmerp.common.enums.TRACK;
import com.vmerp.common.exception.CannotSetTwiceException;
import com.vmerp.common.util.SecurityUtils;

import lombok.ToString;
import lombok.experimental.SuperBuilder;

/**
 * 모든 JavaBean에서 공통으로 사용될 변수를 가진 모델.
 * 모든 bean은 이 클래스를 상속해야 한다. 
 *
 */
@ToString
@SuperBuilder
public class BaseModel {

	public BaseModel() {
		baseUserId = SecurityUtils.getUserId();
		// insert, update시 userId세팅 테스트
		// System.out.println(this.getClass().getName() + " baseUserId=" + baseUserId );
	}

	/**
	 * mapper에서 insert, update 용 등록자 아이디
	 */
	@JsonIgnore
	private String baseUserId;
	
	/**
	 * 등록자 아이디
	 */
	private String insertUserId;
	/**
	 * 등록 일시
	 */
	private LocalDateTime insertDatetime;
	/**
	 * 수정자 아이디
	 */
	private String updateUserId;
	/**
	 * 수정 일시
	 */
	private LocalDateTime updateDatetime;

	/**
	 * FlexGrid에서 `추가`, `수정`한 데이터의 순서를 따져야할 경우 
	 * 저장할때 지정되는 인덱스
	 */
	private Integer _si_;
	
	/**
	 * FlexGrid에서 데이터의 추가, 수정, 삭제 타입(TrackType).
	 * `추가`는 "A", `수정`은 "E", `삭제`는 "R"
	 */
	private TRACK _tr_;

	/**
 	 * 조회결과는 무의미 하므로 Json에서는 제외된다.  
	 * @return 저장 순서
	 */
	@JsonIgnore
	public Integer getSi() {
		return _si_;
	}

	/**
	 * Spring에서 request의 파라미터를 bean으로 매핑할때 한번만 실행되고
	 * 개발자는 호출해서는 않된다. 
	 * @param si
	 */
	public void set_si_(Integer si) {
		if (_si_ != null) {
			throw new CannotSetTwiceException();
		}
		this._si_ = si;
	}

	/**
	 * 조회결과는 무의미 하므로 Json에서는 제외된다.
	 * @return
	 */
	@JsonIgnore
	public TRACK getTr() {
		return _tr_;
	}

	/**
	 * Spring에서 request의 파라미터를 bean으로 매핑할때 한번만 실행되고
	 * 개발자는 호출해서는 않된다. 
	 * @param si
	 */
	public void set_tr_(TRACK tr) {
		if (_tr_ != null) {
			throw new CannotSetTwiceException();
		}
		this._tr_ = tr;
	}

	/**
	 * mybatis mapper.xml에서 `insertUserId`와 `updateUserId`의 userId로 사용한다.
 	 * 조회결과는 무의미 하므로 Json에서는 제외된다.  
	 * @return
	 */
	public void setBaseUserId(String baseUserId) {
		this.baseUserId = baseUserId;
	}
	
	@JsonIgnore
	public String getBaseUserId() {
		return SecurityUtils.getUserId();
	}


	public String getInsertUserId() {
		return insertUserId;
	}

	public void setInsertUserId(String insertUserId) {
		this.insertUserId = insertUserId;
	}

	public LocalDateTime getInsertDatetime() {
		return insertDatetime;
	}

	public void setInsertDatetime(LocalDateTime insertDatetime) {
		this.insertDatetime = insertDatetime;
	}

	public String getUpdateUserId() {
		return updateUserId;
	}

	public void setUpdateUserId(String updateUserId) {
		this.updateUserId = updateUserId;
	}

	public LocalDateTime getUpdateDatetime() {
		return updateDatetime;
	}

	public void setUpdateDatetime(LocalDateTime updateDatetime) {
		this.updateDatetime = updateDatetime;
	}

}
  • popupBaseModel
package com.vmerp.common.model;

import com.fasterxml.jackson.annotation.JsonIgnore;

import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.SuperBuilder;

/**
 * 팝업프로그램의 조회조건으로 사용는 모델.
 * 공통으로 사용할 팝업코드와 팝업명칭 필드를 가짐
 * @author yhcha
 *
 */
@ToString
@SuperBuilder
@NoArgsConstructor
public class PopupBaseModel extends BaseModel {

	/**
	 * 팝업 자동 조회시 sql에서 `코드컬럼`의 이름
	 */
	private String codeCol;
	/**
	 * 팝업 자동 조회시 sql에서 `코드컬럼`의 조건으로 사용될 값
	 */
	private String code;
	/**
	 * 팝업 자동 조회시 sql에서 `명칭컬럼`의 이름
	 */
	private String nameCol;
	/**
	 * 팝업 자동 조회시 sql에서 `명칭컬럼`의 조건으로 사용될 값
	 */
	private String name;
	

	/**
 	 * 조회결과는 무의미 하므로 Json에서는 제외된다.  
	 */
	@JsonIgnore
	public String getCodeCol() {
		return codeCol;
	}

	public void setCodeCol(String codeCol) {
		this.codeCol = codeCol;
	}

	/**
 	 * 조회결과는 무의미 하므로 Json에서는 제외된다.  
	 */
	@JsonIgnore
	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	/**
 	 * 조회결과는 무의미 하므로 Json에서는 제외된다.  
	 */
	@JsonIgnore
	public String getNameCol() {
		return nameCol;
	}

	public void setNameCol(String nameCol) {
		this.nameCol = nameCol;
	}

	/**
 	 * 조회결과는 무의미 하므로 Json에서는 제외된다.  
	 */
	@JsonIgnore
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

Hello