JAVA의 원시타입은 null 값을 싫어해..

장준휴·2024년 2월 7일
0

Spring Boot

목록 보기
4/4

어떻게 알았어?


환자의 생체 데이터를 활용하여 패혈증 지수를 예측하는 서비스를 만드는 프로젝트 진행 중 Pysionet 2019 에서 제공하는 환자 데이터를 DB에 입력하였다.

이후 입력된 데이터를 JPA를 사용해서 가져오려고 했다.

@Entity
@Data
@Persistent
public class Smart_vital {
	
	//바이탈 넘버
	@Id
	@Column
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int num;
	
	// 환자번호
	@Column
	private int patientnum;
	
	// 패혈증 수치
	@Column
	private float sepsisscore;
	
	// 검사 일시 default값 지정
	@Column(columnDefinition = "datetime default now()", insertable = false, updatable = false)
	private String sepdate;
	// 산소포화도
	@Column
	private float o2sat;
	
	// 체온
	@Column
	private float temp;
	// 수축기 혈압
	@Column
	private int sbp;
	// 이완기 혈압
	@Column
	private int dbp;
	//호흡수
	@Column
	private int resp;
	// 심장박동수
	@Column
	private int hr;
	// 평균 동맥압 평균 혈압
	@Column
	private float map;
	
	//이산화 탄소 농도
	@Column
	private float etco2;
	
	//과잉 탄산염
	@Column
	private float baseexcess;
	
	//탄산수소이온
	@Column
	private float hco3;
	
	//흡기 손소분율
	@Column
	private float fio2;
	
	//산성 또는 알카리성 정도를 나타내는 척도
	@Column
	private float ph;
	
	//이산화 탄소 분압
	@Column
	private float paco2;
	
	//동맥혈의 산소포화도
	@Column
	private float sao2;
	
	//간 기능을 평가하기위해 사용하는 효소
	@Column
	private float ast;
	
	//신장기능 평가
	@Column
	private float bun;
	
	//알카리성 인산효소
	@Column
	private float alkalinephos;
	
	//칼슘
	@Column
	private float calcium;
	
	//염소이온
	@Column
	private float chloride;
	
	//크레아틴
	@Column
	private float creatinine;
	
	//직접빌리루빈
	@Column
	private float bilirubindirect;
	
	//혈당
	@Column
	private float glucose;
	
	//라틱산
	@Column
	private float lactate;
	
	//마그네슘
	@Column
	private float magnesium;
	
	//인
	@Column
	private float phosphate;
	
	//칼륨
	@Column
	private float potassium;
	
	//총 빌리루빈
	@Column
	private float bilirubintotal;
	
	//트로포닌
	@Column
	private float troponini;
	
	//헤마토크리트
	@Column
	private float hct;
	
	//헤모글로빈
	@Column
	private float hgb;
	
	//부분혈장응고시간
	@Column
	private float ptt;
	
	//백혈구 수
	@Column
	private float wbc;
	
	//혈액응고 역할 단백질
	@Column
	private float fibrinogen;
	
	//혈소판 수
	@Column
	private float platelets;

}

(아무리 봐도 너무 많은 생체 데이터 컬럼...)

근데 실행해보니 ㄷㄷ..

2024-02-07 17:20:40.260 ERROR 10904 --- [nio-8088-exec-2] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [/boot] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: Null value was assigned to a property [class com.smhrd.smart.entity.smart_vital1.alkalinephos] of primitive type setter of com.smhrd.smart.entity.smart_vital1.alkalinephos; nested exception is org.hibernate.PropertyAccessException: Null value was assigned to a property [class com.smhrd.smart.entity.smart_vital1.alkalinephos] of primitive type setter of com.smhrd.smart.entity.smart_vital1.alkalinephos] with root cause

이런 끔찍한 오류가 발생했다..

바로 Googling GoGo~~


어떤 오류?


patient_vital 테이블에 존재하는 데이터는 이렇게 Null 값이 존재한다.

그래서 처음에 JPA는 NULL 값을 못받는 줄 알고 @Column 어노테이션에 nullable 속성을 넣어줬다

@Column
private float temp;

이랬던 코드가

@Column(nullable = true)
private float temp;

요래 됐슴다

하지만 오류는 여전히...


그래서 다시 구글링 시작!!

열심히 찾아본 결과

JPA는 entity에서 필드를 원시형 데이터 타입을 한다.

  • JPA를 사용하여 엔티티를 저장할 때, 원시 타입에 NULL 값을 할당 하려고 하면 오류가 발생한다.



어떻게 해결해?


해결 방법은 진짜 간단했다.

원시형 데이터를 Wrapper 타입의 데이터 형태로 바꾸면 된다.

int > Integer
float > Float
double > Double
boolean > Boolean
long > Long

이런식으로!

그래서 나도 싹 바꿨다.
그 많은 컬럼을...

	//바이탈 넘버
		@Id
		@Column
		private int vitalnum;

		// 환자번호
		@Column
		private int patientnum;

		// 패혈증 수치
		@Column
		private Float sepsisscore;

		// 검사 일시 default값 지정
		@Column
		private String sepdate;
		// 산소포화도
		@Column(nullable = true)
		private Float o2sat;

		// 체온
		@Column(nullable = true)
		private Float temp;
		// 수축기 혈압
		@Column(nullable = true)
		private Integer sbp;
		// 이완기 혈압
		@Column(nullable = true)
		private Integer dbp;
		//호흡수
		@Column(nullable = true)
		private Integer resp;
		// 심장박동수
		@Column(nullable = true)
		private Integer hr;
		// 평균 동맥압 평균 혈압
		@Column(nullable = true)
		private Float map;

		//이산화 탄소 농도
		@Column(nullable = true)
		private Float etco2;

		//과잉 탄산염
		@Column(nullable = true)
		private Float baseexcess;

		//탄산수소이온
		@Column(nullable = true)
		private Float hco3;

		//흡기 손소분율
		@Column(nullable = true)
		private Float fio2;

		//산성 또는 알카리성 정도를 나타내는 척도
		@Column(nullable = true)
		private Float ph;

		//이산화 탄소 분압
		@Column(nullable = true)
		private Float paco2;

		//동맥혈의 산소포화도
		@Column(nullable = true)
		private Float sao2;

		//간 기능을 평가하기위해 사용하는 효소
		@Column(nullable = true)
		private Float ast;

		//신장기능 평가
		@Column(nullable = true)
		private Float bun;

		//알카리성 인산효소
		@Column(nullable = true)
		private Float alkalinephos;

		//칼슘
		@Column(nullable = true)
		private Float calcium;

		//염소이온
		@Column(nullable = true)
		private Float chloride;

		//크레아틴
		@Column(nullable = true)
		private Float creatinine;

		//직접빌리루빈
		@Column(nullable = true)
		private Float bilirubindirect;

		//혈당
		@Column(nullable = true)
		private Float glucose;

		//라틱산
		@Column(nullable = true)
		private Float lactate;

		//마그네슘
		@Column(nullable = true)
		private Float magnesium;

		//인
		@Column(nullable = true)
		private Float phosphate;

		//칼륨
		@Column(nullable = true)
		private Float potassium;

		//총 빌리루빈
		@Column(nullable = true)
		private Float bilirubintotal;

		//트로포닌
		@Column(nullable = true)
		private Float troponini;

		//헤마토크리트
		@Column(nullable = true)
		private Float hct;

		//헤모글로빈
		@Column(nullable = true)
		private Float hgb;

		//부분혈장응고시간
		@Column(nullable = true)
		private Float ptt;

		//백혈구 수
		@Column(nullable = true)
		private Float wbc;

		//혈액응고 역할 단백질
		@Column(nullable = true)
		private Float fibrinogen;

		//혈소판 수
		@Column(nullable = true)
		private Float platelets;

이렇게 하니까 오류 해결!


정리


jpa에서 원시형 데이터 타입은 null 값을 받지 못하기 때문에 wrapper 타입으로 필드의 타입을 지정해줘야한다.
profile
나는야 토마토

2개의 댓글

comment-user-thumbnail
2024년 2월 7일

뤠퍼뤠퍼

1개의 답글