반응형

JPA 기본 설정 완성 후 

 

소스 작업 전 테스트 소스를 먼저 만들어보자

 

Base도메인 설정

 

@MappedSuperclass
@EntityListeners(value = { AuditingEntityListener.class })
//spring jpa AuditingEntityListener 에서 가져옴
// 해당 클래스가 적용되면 엔티티가 데이터베이스에 추가 / 변경될 때 자동으로 시간 값을 저장
// AuditingEntityListener 활성화 하기 위해 프로젝트 설정에 @EnableJpaAuditing 추가 해야함
@Getter
public class BaseEntity {

    @CreatedDate
    @Column(name = "regdate", updatable = false)
    private LocalDateTime regDate;

    @LastModifiedDate
    @Column(name = "moddate")
    private LocalDateTime modDate;


}

repository 인터페이스 설정

 

// spring jpa data 이용할 때 JpaRepository 인터페이스를 이용해서
// 인터페이스 선언만으로 데이터 베이스 기본 작업 CRUD 와 페이징 처리가 가능하다.

public interface BoardRepository extends JpaRepository<Board, Long> {}

실제 사용 Board 도메인 설정

@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Board extends BaseEntity {
    //BaseEntity 에서 전체 적용 되는 데이터베이스 값을 가져온다

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    // GenerationType.IDENTITY 데이터 베이스에 위임-auto_increment (mysql/maria)
    private Long bno;

    @Column(length = 500 , nullable = false) //컬럼 길이와 null  허용 여부
    private String title;

    @Column(length = 2000 , nullable = false)
    private String content;

    @Column(length = 50 , nullable = false)
    private String writer;

}

 

인서트 테스트 코드 작성 후 RUN ~~~

@SpringBootTest
@Log4j2
public class BoardRepositoryTest {

    @Autowired
    private BoardRepository boardRepository;

    @Test
    public void testInsert(){
        IntStream.rangeClosed(1,100).forEach( i ->{
            Board board = Board.builder()
                    .title("제목 ... "+i)
                    .content("내용 ... "+ i)
                    .writer("user"+(i%10))
                    .build();
            Board result = boardRepository.save(board);
            log.info("BNO : " + result.getBno());
        });
    }
}

위 코드를 GPT가 분석해 줌

위의 자바 코드는 빌더 패턴을 이용하여 board 객체를 생성하는 코드입니다.
빌더 패턴은 복잡한 객체를 생성할 때, 객체의 생성과 표현을 분리하여 객체를 생성하는 디자인 패턴입니다. 이 코드에서는 빌더를 사용하여 제목, 내용 및 작성자가 있는 게시판 객체를 생성합니다.

빌더는 메소드 호출 체인으로 사용되고 있습니다. title() 메소드는 i 변수의 값과 문자열을 연결하여 게시판의 제목을 설정합니다. content() 메소드는 i 변수의 값과 문자열을 연결하여 게시판의 내용을 설정합니다. writer() 메소드는 i를 10으로 나눈 나머지와 문자열을 연결하여 게시판의 작성자를 설정합니다.

마지막으로 build() 메소드가 호출되어 빌더가 설정한 값으로 새로운 board 객체가 생성되고 반환됩니다.

 

실제 스프링 띄우면서 JPA 테이블 생성하고 인서트 까지 이상없이 실행

Starting Gradle Daemon...
Gradle Daemon started in 1 s 5 ms

> Task :compileJava
> Task :processResources UP-TO-DATE
> Task :classes
> Task :compileTestJava
> Task :processTestResources NO-SOURCE
> Task :testClasses
> Task :test

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.0.5)

2023-04-22T17:35:45.154+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : Starting BoardRepositoryTest using Java 17.0.4 with PID 6100 (started by user in C:\Users\user\IdeaProjects\jisou)
2023-04-22T17:35:45.155+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : No active profile set, falling back to 1 default profile: "default"
2023-04-22T17:35:45.570+09:00  INFO 6100 --- [    Test worker] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2023-04-22T17:35:45.616+09:00  INFO 6100 --- [    Test worker] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 38 ms. Found 1 JPA repository interfaces.
2023-04-22T17:35:45.925+09:00  INFO 6100 --- [    Test worker] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2023-04-22T17:35:45.976+09:00  INFO 6100 --- [    Test worker] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 6.1.7.Final
2023-04-22T17:35:46.227+09:00  INFO 6100 --- [    Test worker] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2023-04-22T17:35:46.373+09:00  INFO 6100 --- [    Test worker] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@18b40fe6
2023-04-22T17:35:46.375+09:00  INFO 6100 --- [    Test worker] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2023-04-22T17:35:46.427+09:00  INFO 6100 --- [    Test worker] SQL dialect                              : HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
Hibernate: 
    
    create table board (
       bno bigint not null auto_increment,
        moddate datetime(6),
        regdate datetime(6),
        content varchar(2000) not null,
        title varchar(500) not null,
        writer varchar(50) not null,
        primary key (bno)
    ) engine=InnoDB
2023-04-22T17:35:47.117+09:00  INFO 6100 --- [    Test worker] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2023-04-22T17:35:47.126+09:00  INFO 6100 --- [    Test worker] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2023-04-22T17:35:47.217+09:00  WARN 6100 --- [    Test worker] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2023-04-22T17:35:47.663+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : Started BoardRepositoryTest in 2.684 seconds (process running for 3.944)
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)
2023-04-22T17:35:47.872+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : BNO : 1
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)
2023-04-22T17:35:47.891+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : BNO : 2
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)
2023-04-22T17:35:47.907+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : BNO : 3
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)
2023-04-22T17:35:47.925+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : BNO : 4
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)
2023-04-22T17:35:47.942+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : BNO : 5
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)
2023-04-22T17:35:47.959+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : BNO : 6
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)
2023-04-22T17:35:47.974+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : BNO : 7
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)
2023-04-22T17:35:47.989+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : BNO : 8
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)
2023-04-22T17:35:48.014+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : BNO : 9
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)
2023-04-22T17:35:48.030+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : BNO : 10
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)
2023-04-22T17:35:48.047+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : BNO : 11
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)
2023-04-22T17:35:48.060+09:00  INFO 6100 --- [    Test worker] o.d.j.repository.BoardRepositoryTest     : BNO : 12
Hibernate: 
    insert 
    into
        board
        (content, moddate, regdate, title, writer) 
    values
        (?, ?, ?, ?, ?)

디비 인서트 확인

반응형
반응형

gradle could not find mysql:mysql-connector-java

 

build.gradle 설정 파일에 아래 처럼 설정 되어 있는걸

 

 

 

runtimeOnly  'mysql:mysql-connector-java'

 

>>  아래 처럼 변경 하고 다시 빌드 하니 오류가 해결 됨

runtimeOnly 'com.mysql:mysql-connector-j'

 

시간이 지나면서 스프링의 버전이 업데이트되고, mysql을 연동하는 gradle입력 코드가 변경 되었다고 한다 

 

출처 : https://skyriv312079.tistory.com/35

 

[Spring] Spring boot와 Mysql 연동 (Gradle)

스프링을 이용해 공부를 하면서 기존에는 H2 데이터베이스를 사용하다가 Mysql을 사용해서 연결을 해보려고 한다. application.properties과 build.gradle의 파일을 비교 변경하면서 진행하려고 한다. build.g

skyriv312079.tistory.com

 

 

성공 ~

 

 

 

반응형
반응형

ResponseDTO.java

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ResponseDTO <T>{
    private String error;
    private List<T> data;
}

Hello.java

import com.example.demo230123.dto.ResponseDTO;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

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

@RestController
public class Hello {

    @GetMapping("/testResponseBody")
    public ResponseDTO<String> testControllerRequestBody(){
        List<String> list = new ArrayList<String>();
        list.add("hello world I'm ResponseDTO");
        ResponseDTO<String> res = ResponseDTO.<String>builder().data(list).build();
        return res;
    }

    @GetMapping("/testResponseEntity")
    public ResponseEntity<?> testControllerRequestEnitity(){
        List<String> list = new ArrayList<String>();
        list.add("hello world I'm ResponseEntity And you got 400 !");
        ResponseDTO<String> res = ResponseDTO.<String>builder().data(list).build();
        return ResponseEntity.badRequest().body(res);
    }
}

restApi Test

responseBody
ResponseEntity<?>

가끔 http 상태코드( ResponseEntity ) 변경 해야 할때..까먹어서 적어둠 

 

반응형
반응형

repository 만들고 JpaSpecificationExecutor 상속 받아

제공하는 findAll()메서드에서 사용한다.

참고 URL : groti.tistory.com/49

jpa는 알고 나면 쉬운거 같다..

근데 그냥 쿼리 쓰는게 더 편해 ㅠㅠ

반응형
반응형

@PostConstruct 어노테이션 설정해놓은

init 메소드는 WAS가 올라갈때 실행된다. 


 

    @PostConstruct
    private void init() {
        log.info("@PostConstruct ------ WAS 올라갈때 실행");
    }

 

 

출처 https://javaslave.tistory.com/48

반응형
반응형

이클립스에서 분명 사용하는 bean  리스트를 본것 같은데.. 아무리 찾아도 안나옴..

 

그래서 로딩된  bean  목록 출력하는것 소스

 

    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    
    
    public class RestController {
        
    @Autowired
    private DefaultListableBeanFactory dfBean;
    
    
    @GetMapping("/webportalif/getbean")
    public void getBean () {
        for(String name : dfBean.getBeanDefinitionNames()) {
            log.info(" INFO BEAN NAME ===  "+name);
        }
    }
    
    }
    
    출력..
    
11:28:21.157 [http-nio-8080-exec-6] INFO   c.m.w.r.interceptor.WebInterceptor.preHandle 43  - Request URI:/webportalif/getbean, method:GET
11:28:21.158 [http-nio-8080-exec-6] INFO   c.m.w.rest.controller.RestController.getBean 42  -  INFO BEAN NAME ===  org.springframework.context.annotation.internalConfigurationAnnotationProcessor
11:28:21.158 [http-nio-8080-exec-6] INFO   c.m.w.rest.controller.RestController.getBean 42  -  INFO BEAN NAME ===  org.springframework.context.annotation.internalAutowiredAnnotationProcessor
11:28:21.158 [http-nio-8080-exec-6] INFO   c.m.w.rest.controller.RestController.getBean 42  -  INFO BEAN NAME ===  org.springframework.context.annotation.internalCommonAnnotationProcessor
11:28:21.158 [http-nio-8080-exec-6] INFO   c.m.w.rest.controller.RestController.getBean 42  -  INFO BEAN NAME ===  org.springframework.context.event.internalEventListenerProcessor
11:28:21.158 [http-nio-8080-exec-6] INFO   c.m.w.rest.controller.RestController.getBean 42  -  INFO BEAN NAME ===  org.springframework.context.event.internalEventListenerFactory
11:28:21.158 [http-nio-8080-exec-6] INFO   c.m.w.rest.controller.RestController.getBean 42  -  INFO BEAN NAME ===  restApplication
11:28:21.159 [http-nio-8080-exec-6] INFO   c.m.w.rest.controller.RestController.getBean 42  -  INFO BEAN NAME ===  org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
11:28:21.159 [http-nio-8080-exec-6] INFO   c.m.w.rest.controller.RestController.getBean 42  -  INFO BEAN NAME ===  webServiceConfig
11:28:21.159 [http-nio-8080-exec-6] INFO   c.m.w.rest.controller.RestController.getBean 42  -  INFO BEAN NAME ===  restController

반응형
반응형

기본 설계가 없는 플젝 빠르게 만들고 있는데

개발만 빨리 해달라더니.. 빠르게 하니 이것저것 요구하고 있음요 

 

기분좋게 해야 되는데 왜케 구찮을까요~~ㅎㅎ

 

인터셉터 사용

HandlerInterceptorAdapter 상속받은 클래스에서 

 

preHandle 인터셉터 에서 애러가 발생

 

return false; 해주면 그 상태에서 모든게 끝난다

 

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
        if(토큰이 없다면) {
            log.debug(" AuthKey  empty");
            response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
            return false;
        }
    
    }

 

괜히 reponse.end 찾고 response에서 뭘 해볼려고 했는데 리턴값이 boolean 였던걸 몰랐다...

 

오늘 지른 모니터..

반응형
반응형

여러 디비 거쳐서 합친 리스트 데이터라 개 귀찮아서 Dto 안만든고 그대로 뿌린다고 @ResponseBody 로 뿌렸다

근데 

특정 애러면 바로 404 로 http 응답해주라는 요청..

HttpServletResponse response 파라미터 받아서 

response.sendError 애러 처리 하려고 했는데 리턴값 어쩌고 ..애러 발생... 폭풍검새

 

 

해결코드 !!! ㅎㅎㅎㅎㅎ

    @ResponseBody
    public Map<String, Object> 메서드()  throws NotFoundException {
    	if(1){
    		return map;
        }else{
            throw new NotFoundException();
        }
    }
    
    @ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Not Found")
    public class NotFoundException extends Exception {
        public NotFoundException() {
        }
    } 

좀 꺼림직 한데..

 

고객이 수시로 마구마구 요구사항 악마처럼 던져서 신경쓰기 개 귀찮

돌아가면 된거~~ 끝

 

뭘봐

반응형
반응형
{

    "id":"test",

       "status":

       { 

         "location":"E1",

         "mode":"2",

         "starttime":"2020/09/30 12:20:00",

         "endtime":"2020/09/30 13:50:00"

       },   

       "time":"2020/09/01 11:14:12"

}

 

위 json 넘어온 데이터 스프링 컨트롤러에서 받아서.

 

public test (@RequestBody Map<String, Object> param) {

}

 

넘어온 값을 아래처럼 json 다시 만들고 싶을때

{

    "id":"test",

       "status":

       { 

         "location":"E1",

         "mode":"2",

         "starttime":"2020/09/30 12:20:00",

         "endtime":"2020/09/30 13:50:00"

       },   

    "reg":{

      "id": "test

    }



}

 

map 데이터 신규 생성하여서 param map에 put 하면 해결 됨 

        //put renew 
        Map<String,Object> temp = new HashMap<>();
        temp.put("id",param.get("id"));  
        param.put("reg", temp);
        

 

반대로 던져줄 response도 개념은 같다

 

던질 맵 하나 만들고 키 추가한 후 계속 PUT PUT PUT PUT ~~~

 

개발 10년차 삽질

반응형
반응형

뭔가 인증할때 구현하면 개 편함

 

api 요청전 키 검증용으로 진행

 

 

    @Bean
    public RestApiInterceptor restApiInterceptor() {
        return new RestApiInterceptor();
    }

 

빈 생성

 

    // Interceptor 등록
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(restApiInterceptor()).addPathPatterns("/api/v1/**");
    }

 

public class RestApiInterceptor extends HandlerInterceptorAdapter {
    
    private static final Logger logger = LoggerFactory.getLogger(RestApiInterceptor.class);
        logger.debug("===============================================");
        logger.debug("==================== BEGIN ====================");
        
        return super.preHandle(request, response, handler);
    }
    
    
        @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        logger.debug("==================== END ======================");
        logger.debug("===============================================");
    }   

 

이케 하면 /api/v1/

시작하는 url 은 

preHandle 검증후 

 이상없으면 로직실행

postHandle 로 end

 

아래 블로그글 로 사용법 참고.

 

congsong.tistory.com/24

 

스프링 부트(Spring Boot) - 인터셉터(Interceptor) 적용하기 [개발을 시작해봐요!]

이전 글에서는 프로젝트에 로그백(Logback)을 적용해서 SQL 쿼리 로그와 게시글의 정보를 테이블 형태로 출력하는 방법에 대해 알아보았습니다. 이번 글에서는 스프링에서 제공해주는 기능인 인터

congsong.tistory.com

 

 

 

반응형

+ Recent posts