기본 콘텐츠로 건너뛰기

keytool 사용법

keytool.exe -genkey -alias juheon -keyalg RSA -keypass 1234qwer -storepass 1234qwer -keystore juheon.jks  keytool.exe -export -alias juheon -storepass 1234qwer -file juheon.cer -keystore juheon.jks  keytool.exe -importkeystore -srckeystore juheon.jks -destkeystore juheon.key.p12 -deststoretype PKCS12  D:\Java\32bit\jdk1.5.0_22\jre\lib\security\cacert  D:\Java\32bit\jdk1.5.0_22\bin\keytool.exe -import -alias tsasample -keystore  D:\Java\32bit\jdk1.5.0_22\jre\lib\security\cacert -file D:\workspace\Servers\tsa-server-web-config\tomcat.cer  keytool -import -alias somansa -keystore C:\Program Files\Java\jdk1.8.0_102\jre\lib\security\cacert -file c:\somansa.cer #인증서 생성  keytool -genkey -alias keyAlias -keyalg RSA -keypass changeit -storepass changeit –validity 9999 -keystore keystore.jks  keytool -export -alias keyAlias -storepass changeit -file server.cer -keystore keystore.jks  keytool -import -v -trustcacerts -alias keyAlias -file server.cer -keystore cacerts.jks -keypass changeit

Spring boot hello world (2)

H2, Hibernate 연동




H2 dependency 추가

build.gradle 파일

dependencies {
 ...
 compile("com.h2database:h2:1.4.193")
 ...
}

dependency를 추가하고 gradle project refresh한다.

Application 설정

spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.datasource.url=jdbc:h2:file:C:\Users\git\helloworld\h2_db;AUTO_SERVER=TRUE

#spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
#spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

설정하고 브라우져에서 h2 관리콘솔 접속했더니 아래와 같은 에러가 뜬다.

Caused by: java.lang.IllegalStateException: Unsupported type 17 [1.4.200/3]

H2 버전도 바꿔보고,  URL도 바꿔보고, 계정도 바꿔보고 별짓을 해도 안되더니 혹시나 해서 cmd에서 gradle로 빌드하고 jar를 실행했더니 잘된다!!!! 뻑킹 뭐야!!!!

그러고 나서 다시 이클립스에서 spring boot 프로젝트를 중지했다가 재시작하니 잘되네??

뭔가 이클립스 스프링 플러그인이 굉장히 불안한거 같다.

테이블, 데이터 생성

H2 관리 콘솔에서 테이블, 데이터를 생성한다.


DROP TABLE IF EXISTS TBL_EMPLOYEES;
  
CREATE TABLE TBL_EMPLOYEES (
  id INT AUTO_INCREMENT  PRIMARY KEY,
  first_name VARCHAR(250) NOT NULL,
  last_name VARCHAR(250) NOT NULL,
  email VARCHAR(250) DEFAULT NULL
);

INSERT INTO TBL_EMPLOYEES (first_name, last_name, email) VALUES
  ('Lokesh', 'Gupta', 'abc@gmail.com'),
  ('Deja', 'Vu', 'xyz@email.com'),
  ('Caption', 'America', 'cap@marvel.com');



귀찮으니 그냥 sa 계정에서...


Hibernate 추가

build.gradle 파일
dependencies {
  ...
  compile("org.hibernate:hibernate-core:5.4.9.Final")
  ...
}

dependency를 추가하고 gradle project refresh한다.

소스코드 작성


Entity

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

@Entity
@Table(name="TBL_EMPLOYEES")
public class Employee {
 
 @Id
 @GeneratedValue
 private Long id;
 
 @Column(name = "first_name")
 private String firstName;
 
 @Column(name = "last_name")
 private String lastName;
 
 @Column(name="email", nullable=false, length=200)
 private String email;
  
 //add getter, setter

 @Override
 public String toString() {
  return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
 }
}

ToStringBuilder class를 사용하기 위해 org.apache.commons.lang3 패키지를 추가하였다.

dependencies {
 ...
 compile("org.apache.commons:commons-lang3:3.9")
 ...
}


Repository

import org.springframework.data.jpa.repository.JpaRepository;

import com.ha.helloworld.entity.Employee;

public interface EmployeeRespository extends JpaRepository{

}


Service

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ha.helloworld.entity.Employee;
import com.ha.helloworld.repository.EmployeeRespository;

@Service
public class EmployeeService {

 @Autowired
 EmployeeRespository repository;
 
 public List getAllEmployees() {
  List list = this.repository.findAll();
  
  if(list == null) return new ArrayList();
  
  return list;
 }
 
 public Employee getEmployeeById(Long id) {
  if(id == null) return null;
  
  Optional option = this.repository.findById(id);
  
  if(option.isPresent()) return option.get();
  
  return null;
 }
 
 public Employee createOrUpdateEmployee(Employee entity) {
  
  Employee data = this.getEmployeeById(entity.getId());
  
  if(data == null) data = new Employee();
  
  data.setFirstName(entity.getFirstName());
  data.setLastName(entity.getLastName());
  data.setEmail(entity.getEmail());
  
  this.repository.save(data);
  
  return data;
 }
 
 public void deleteEmployeeById(Long id) {
  this.repository.deleteById(id);
 }
}


Controller

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.ha.helloworld.entity.Employee;
import com.ha.helloworld.service.EmployeeService;

@Controller
@RequestMapping("/employee")
public class EmployeeController {

 @Autowired
 EmployeeService employeeService;
 
 @GetMapping
 public ResponseEntity> getAllEmployee() {
  List list = this.employeeService.getAllEmployees();
  
  ResponseEntity> response = new ResponseEntity<>(list, new HttpHeaders(), HttpStatus.OK);
  
  return response;
 }
 
 @GetMapping("/{id}")
    public ResponseEntity getEmployeeById(@PathVariable("id") Long id) {
        Employee entity = employeeService.getEmployeeById(id);
 
        return new ResponseEntity(entity, new HttpHeaders(), HttpStatus.OK);
    }
 
    @PostMapping
    public ResponseEntity createOrUpdateEmployee(Employee employee) {
        Employee updated = employeeService.createOrUpdateEmployee(employee);
        return new ResponseEntity(updated, new HttpHeaders(), HttpStatus.OK);
    }
 
    @DeleteMapping("/{id}")
    public ResponseEntity deleteEmployeeById(@PathVariable("id") Long id) {
     employeeService.deleteEmployeeById(id);
        return ResponseEntity.ok().build();
    }
}

Rest API 형식이라 Postman 프로그램으로 호출 테스트 해보았다.

http://localhost/employee

결과는 아래 처럼 나옴

[
    {
        "id": 1,
        "firstName": "Lokesh",
        "lastName": "Gupta",
        "email": "abc@gmail.com"
    },
    {
        "id": 2,
        "firstName": "Deja",
        "lastName": "Vu",
        "email": "xyz@email.com"
    },
    {
        "id": 3,
        "firstName": "Caption",
        "lastName": "America",
        "email": "cap@marvel.com"
    }
]


데이터 추가 API를 호출하면 아래와 같은 오류가 난다.

2019-12-13 01:07:41 - Sequence "HIBERNATE_SEQUENCE" not found; SQL statement:
call next value for hibernate_sequence [90036-193]
2019-12-13 01:07:59 - Failed to complete request: org.springframework.orm.jpa.JpaSystemException: could not prepare statement; nested exception is org.hibernate.exception.GenericJDBCException: could not prepare statement
2019-12-13 01:07:59 - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: could not prepare statement; nested exception is org.hibernate.exception.GenericJDBCException: could not prepare statement] with root cause
org.h2.jdbc.JdbcSQLException: Sequence "HIBERNATE_SEQUENCE" not found; SQL statement:
call next value for hibernate_sequence [90036-193]
 at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
 at org.h2.message.DbException.get(DbException.java:179)
 at org.h2.message.DbException.get(DbException.java:155)

엔티티에 아이디 생성 annotation아래와 같이 설정하면 JPA는 default로 id를 "HIBERNATE_SEQUENCE"라는 sequence table에서 가져오려고 한다. sequence table 만들지 않았으므로 오류가 나는것.
@Id
 @GeneratedValue
 private Long id;

그래서 id 생성을 strategy를 통해 생성하도록 아래와 같이 설정하면 오류가 발생하지 않는다.
@Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Long id;



참고: https://howtodoinjava.com/spring-boot2/spring-boot-crud-hibernate/

댓글

이 블로그의 인기 게시물

Tomcat : context.xml 파일 사용

context.xml 파일을 사용하여 JNDI 등록 사용하는 방법 1. server.xml 파일에 JNDI 등록  server.xml 파일의 GlobalNamingResources노드에 Resource를 등록하고 Host 노드 하위 Context 노드에 ResourceLink노드를 등록하여 많이 사용했다. tomcat 5.5 이전 방식이다. server.xml ... <globalnamingresources>     <!-- Editable user database that can also be used by          UserDatabaseRealm to authenticate users     -->     <resource auth="Container" driverclassname="oracle.jdbc.OracleDriver" maxidle="4" maxtotal="8" name="global.db" password="password" type="javax.sql.DataSource" url="jdbc:oracle:thin:@localhost:1521:xe" username="user">   </resource> </globalnamingresources> ... 2. context.xml 파일 분리 위 방식처럼 server.xml 파일에 모든 context의 정보를 추가하는 방식은 서버에 대한 제어권이 없으면 정보를 변경하기 힘들다. Tomcat 5.5? 이후부터는 context.xml 파일을 분리하여 webapplication에서 별도로 자원을 등록 사용할 수있도록 제공한다. META-INF/context.xml 파일을 위치시키면 Tomcat은 구동시 META-INF 폴더의 context.xml 파일을

Jeus was jsp 컴파일된 파일 경로

WAS 구동시 jsp 에러가 났을때 jsp가 컴파일된 파일을 확인하여 디버깅한다. jeus was jsp 컴파일된 파일 경로 %WAS_HOME%/WEBAPP/WEB-INF/.warjspwork/jeus_jspwork/ jsp 에러의 예) javax.servlet.ServletException: String index out of range: -13 at javax.servlet.http.HttpServlet.service(Unknown Source) at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java(Compiled Code)) at jeus.servlet.engine.RequestDispatcherImpl.processCommonRequestDispatcher(RequestDispatcherImpl.java(Compiled Code)) at jeus.servlet.engine.RequestDispatcherImpl.doForward(RequestDispatcherImpl.java(Compiled Code)) at jeus.servlet.engine.RequestDispatcherImpl.forward(RequestDispatcherImpl.java(Compiled Code)) at com.tomato.jef.servlet.BaseServlet.doDispatch(BaseServlet.java(Inlined Compiled Code)) at com.tomato.jef.bizframe.servlet.XecureHTMLMainServlet.doProcess(XecureHTMLMainServlet.java(Compiled Code)) at com.tomato.jef.bizframe.servlet.XecureHTMLMainServlet.doSessionProcess(Xec

Vmware Fusion Window가 정상 종료가 되지 않을때

* 1번 방법   1. VMWare가 실행된 그 상태에서 Option키를 누르고 위에 메뉴바에서 Virtual Machine 메뉴를 클릭합니다.  2. 종료 메뉴가 Force 메뉴로 바뀌어 있습니다. Force shut down 이나 Force restart 합니다.  * 2번 방법   1. 유틸리티 - 활성 상태 보기로 들어가서 vmware 단어가 포함된 모든 프로세스를 강제종료 합니다.    2. 가상머신의 파일을 찾아갑니다. (eg. Documents/Virtual Machines/ 안에 있습니다.) 그리고 가상머신 파일의 오른쪽을 눌러 "패키지 내용 보기"로 들어갑니다.  3. ".vmem" 확장자로 된 모든 파일을 쓰레기통에 버리고 난 후 모두 비웁니다.  4. 다시 VMWare을 실행합니다. 어떤 오류가 나면 그냥 Disgard 하면됩니다.