Oracle와 mybatis 연동 실습

Back-End/Spring 2019. 6. 5. 16:10

가. mybatis에서 sql query를 작성하는 방법



  1. mapper xml 파일에 작성


  MemoDAO.java (인터페이스)


  MemoDAO.Impl.java (구현클래스)


  memoMapper.xml (mapper)



  2. mapper interface에 작성


  MemoDAO.java : SQL 포함





나. spring02 프로젝트 생성


Spring Legacy Project => Spring MVC project

sample 프로젝트에서 설정파일 복사 :

패키지 이름은 com.example.spring02로 한다.



클래스에 SQL을 같이 써놓는 방식 자주 사용되지는 않음


 

      1. pom.xml 복사


2. src/main/resources/mappers 디렉토리 생성


3. src/main/resources/mappers/sampleMapper.xml 복사


4. src/main/resources/log4j.xml 복사


5. src/main/resources/log4jdbc.log4j2.properties 복사


6. src/main/resources/logback.xml 복사


7. mybatis-config.xml 복사


8. src/main/webapp/WEB-INF/web.xml 복사


9. src/main/webapp/WEB-INF/spring/root-context.xml 복사


10. src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml 복사





root-context.xml (환경설정 xml)


1
2
3
4
5
6
7
8
9
10
11
<!-- Root Context: defines shared resources visible to all other web components -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <!-- 드라이버 클래스 이름이 변경됨 -->
        <property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
        <!-- 연결문자열에 log4jdbc가 추가됨 -->
        <property name="url"
            value="jdbc:log4jdbc:oracle:thin:@localhost:1521/xe" /> //1521과 xe 사이에 /으로 바꾸어준다.
        <property name="username" value="spring" /> //DB에 접속할 아이디를 입력
        <property name="password" value="1234" /> //DB에 접속할 비밀번호를 입력
    </bean>
cs



servlet-context.xml (환경설정 xml)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- Resolves views selected for rendering by @Controllers to .jsp resources 
        in the /WEB-INF/views directory -->
    <beans:bean<!-- Resolves views selected for rendering by @Controllers to .jsp resources 
        in the /WEB-INF/views directory -->
    <beans:bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>
    <!-- 스프링 빈을 태그로 등록하지 않고 자동으로 검색(auto scan) --> 
    <context:component-scan base-package="com.example.spring02.*" />
 
</beans:beans>
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>
    <!-- 스프링 빈을 태그로 등록하지 않고 자동으로 검색(auto scan) --> 
    <context:component-scan base-package="com.example.spring02.*" /> //spring02로 변경한다.
</beans:beans>
cs



home.jsp 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%@ page language="java" contentType="text/html; charset=UTF-8" 
pageEncoding="UTF-8"%>
<!-- 한글 인코딩 부분이 없으면 한글이 깨지기 때문에 인코딩 언어 설정을 다시해주어야 한다. -->
<html>
<head>
<meta http-equiv = "Content-Type" content="text/html; charset=UTF-8">
<title>Home</title>
</head>
<body>
<h1>Hello world!</h1>  
<P>  The time on the server is ${serverTime}. </P>
</body>
</html>
 
cs



MEMO 테이블 생성 

1
2
3
4
5
6
create table memo(
idx number not null primary key, //글번호를 기본키로 한다.
writer varchar2(50not null,
memo varchar2(200not null,
post_date date default sysdate //날짜가 출력되게 한다 (기본값 : 오늘날짜로 한다.)
);
cs



테이블에 자료를 삽입함

1
2
insert into memo(idx,writer,memo)values(1,'kim','메모1');
insert into memo(idx,writer,memo)values(2,'park','메모2');
cs



-Mybatis란 무엇인가?-


JDBC란 Java에서 DB와 연동하고 쓰기위해 사용하는 API 이다.


JDBC는 DB 연동에 필수적으로 사용하는 것인데


이 JDBC만 사용해서 DB 쿼리문을 작성하면 java소스와 쿼리소스가 겹치게 되고 관리가 어려워 진다.


Mybatis는 SQL 쿼리문을 xml 형식의 파일로 분리시켜 저장관리할 수 있고 java 소스에서 xml 태그의 id만 호출하며 개발의 편리함을 제공한다.


Mybatis는 xml 형식의 쿼리파일을 저장 및 호출하는 역할을 내부적으로 처리하는 것.



 Mybatis 사용전 코드 방식

 Mybatis 사용후 코드 방식

 

public Entity selectFAQList(UserConnection conn, Entity param) throws SQLException 

{

    UserStatement stmt = null; //stmt 초기값 선언
    ResultSet rslt = null; //rslt 초기값 선언
    StringBuffer sql = new StringBuffer();
    sql.append("\n SELECT *"); //sql문 뒤에 table1 테이블에 전체요소를 검색하는
    sql.append("\n FROM"); //코드 추가
    sql.append("\n TABLE1");
    stmt = conn.prepareStatement(sql.toString());
    rslt = stmt.executeQuery();
    Entity _DATA = new Entity();
    _DATA.put("_DATA", EntityUtil.ResultSetToClobList(rslt));
    return _DATA;
}

// java 파일 안에 StringBuffer이라는 클래스를 호출해 sql 이라는 객체를 만들어 계속
이어주면서 sql query를 작성하고 있다.
// 다 작성한 다음 작성 된 쿼리를 다른 메소드의 파라미터로 넘기고 리턴하고 있다.
// 이러한 방식은 쿼리가 수정될 때 마다 계속 .java에 들어가 .append( ) 메소드를 추가하고
// 저장해 유지보수가 힘들고 sql query 구문의 분리가 어려워지고 복잡해진다.
// 또한 쿼리 양이 많아질수록 .java 에는 자바코드 뿐만 아니라 쿼리코드로 인해
// 양이 방대해지는 문제가 발생한다.
// 이런 이유로 인해 sql 구문과 java 코드를 분리하였다.

 <?xml version="1.0" encoding="UTF-8"?>

  <ENTITY id="table.getTable1List" type="SQL" return="List">
    <![CDATA[
        SELECT *
            FROM
            TABLE1
    ]]>
    <PARAMS>    
    </PARAMS>
  </ENTITY>

// xml로 빼내서 쿼리문을 작성하면 내부적 처리는 Mybatis에서 모두 처리해주므로
// Entity ID값을 java에서 호출만하면 된다.


append( ) 메소드 : 선택한 요소의 끝에 콘텐츠를 추가

ex ) - sql.append("\n SELECT *"); = sql문 끝에 SELECT * 을 추가함



root-context.xml 에 코드를 추가한다.

(기존방식인 xml파일을따로 만들어 sql을 쓰는 방식을 쓰면 이 방식은 사용하지 않아도 된다.)

인터페이스에 sql을 직접 쓰고싶고, xml을 따로 만들기 싫을때 사용하는 방법

프로젝트의 패키지의 기본클래스를 등록한다는 뜻


1
2
3
4
<!-- mybatis mapper 코드가 포함된 클래스를 찾아서 bean으로 등록하도록 설정해야함 -->
    <!-- com~~~이하의 디렉터리는 다 뒤져서 been으로 등록하도록 설정한다는 뜻 -->
    <mybatis-spring:scan base-package = "com.example.spring02.model.memo" />
</beans>
cs



MemoDTO.java (계층간 데이터 전송 빈 클래스)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.example.spring02.model.memo.dto;
 
import java.util.Date;
 
//계층간 데이터 교환을 위한 DTO 클래스 만들기
public class MemoDTO {
    private int idx;
    private String writer;
    private String memo;
    private Date post_date;
    
    //getter, setter, 기본생성자, 매개변수가 있는 생성자 (writer,memo), toString()
    
    public int getIdx() {
        return idx;
    }
    public void setIdx(int idx) {
        this.idx = idx;
    }
    public String getWriter() {
        return writer;
    }
    public void setWriter(String writer) {
        this.writer = writer;
    }
    public String getMemo() {
        return memo;
    }
    public void setMemo(String memo) {
        this.memo = memo;
    }
    public Date getPost_date() {
        return post_date;
    }
    public void setPost_date(Date post_date) {
        this.post_date = post_date;
    }
    
    public MemoDTO() {} //기본 생성자
    public MemoDTO(String writer, String memo) { //글쓰기와 메모를 생성할 수 있는 생성자
        this.writer = writer;
        this.memo = memo;
    }
    @Override
    public String toString() { //MemoDTO의 객체가 가지고 있는 정보나 값들을 문자열로 만들어 리턴하는 메소드
        return "MemoDTO [idx=" + idx + ", writer=" + writer + ", memo=" + memo + ", post_date=" + post_date + "]";
    }
    
    
}
 
cs



MemoService.java (인터페이스)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.example.spring02.service.memo;
 
import java.util.List;
 
import com.example.spring02.model.memo.dto.MemoDTO;
 
public interface MemoService {
    //같은 인터페이스나 클래스 안에서 메소드이름이 중복되는 것을 오버로딩이라고 한다.
    //그리고 이것을 상속받아 고치는 것을 오버라이딩이라고 한다.
    
    public List<MemoDTO> list(); //목록
    public void insert(MemoDTO dto); //추가 DTO전체에 넘겨서 하는 방법
    public void insert(String writer, String memo); 
    public MemoDTO memo_view(int idx);//상세화면보기
    public void update(MemoDTO dto);//수정
    public void delete(int idx);//삭제
    
}
 
cs



MemoServiceImpl.java (인터페이스 구현 클래스)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.example.spring02.service.memo;
 
import java.util.List;
 
import org.springframework.stereotype.Service;
 
import com.example.spring02.model.memo.dto.MemoDTO;
 
 
@Service
public class MemoServiceImpl implements MemoService {
 
    @Override
    public List<MemoDTO> list() {
        // TODO Auto-generated method stub
        return null;
    }
 
    @Override
    public void insert(MemoDTO dto) {
        // TODO Auto-generated method stub
 
    }
 
    @Override
    public void insert(String writer, String memo) {
        // TODO Auto-generated method stub
 
    }
 
    @Override
    public MemoDTO memo_view(int idx) {
        // TODO Auto-generated method stub
        return null;
    }
 
    @Override
    public void update(MemoDTO dto) {
        // TODO Auto-generated method stub
 
    }
 
    @Override
    public void delete(int idx) {
        // TODO Auto-generated method stub
 
    }
 
}
 
cs



MemberDAO (DB연결)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.example.spring02.model.memo.dao;
 
import java.util.List;
 
import org.apache.ibatis.annotations.Select;
 
import com.example.spring02.model.memo.dto.MemoDTO;
 
public interface MemberDAO {
    //인터페이스는 객체를 생성하지 못함
    //root-context.xml에서 <mybatis-spring:scan base-package = "com.example.spring02.model.memo" />라고 설정을 해놓은것 때문에
    //@Select문 이하~~가 하나의 객체로 완성된다.
    @Select ("select * from memo order by idx desc")
    //현재 list()메소드는 몸체가 없기 때문에 select 어노테이션의 쿼리가 호출됨
    public List<MemoDTO> list();
    
}
 
cs




-어노테이션 정리-


  @Controller : 컨트롤러 bean으로 등록

  @Service : 서비스 bean으로 등록

  @Repository : DAO bean으로 등록


  @Inject == @Autowired : 의존성 주입


  @RequestMapping : (url mapping) url과 메소드를 연결시켜주는 역할을 한다.

  @RequestParam : post 방식이나 get 방식으로 넘어온 개별변수

  @ModelAttribute : DTO로 묶어서 한번에 저장할때 쓴다

  @ResponseBody : 컨트롤러에서 어떤 메소드를 호출한 다음 페이지로 넘어가는것이 아니라 데이터 자체를 넘길때 (제이슨 같은걸로 넘길때)





MemoController.java (컨트롤러 클래스)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.example.spring02.controller.memo;
 
import java.util.List;
 
import javax.inject.Inject;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
 
import com.example.spring02.model.memo.dto.MemoDTO;
import com.example.spring02.service.memo.MemoService;
 
@Controller
//현재 클래스를 컨트롤러 bean으로 등록함
//구조
//컨트롤러에서 서비스를 호출하고, 서비스에서 DAO를 호출하고, DAO에서 SQL이 실행된다.
//반드시 어노테이션 Service, Controller 등을 붙여야 컨트롤러해서 호출이 가능하다.
 
@RequestMapping("/memo/*"// <-이쪽에 작성되는 매핑은 이 클래스의 공통적인 매핑
                            // 이 클래스는 기본적으로 [/memo로 시작한다라는 의미이고 뒤에 *는 뒤에 어떤것이 와도 상관없다는 의미 ]
            // 사용하는 이유 : 매핑을 할시에 여러 매소드들에서 공통적인 경로로 url 매핑을 할때 url 주소를 간략하게 할 수 있기 때문에 사용한다.
                         
 
public class MemoController {
 
    //매핑을 할때는 목록을 먼저 뽑는다.
    @Inject    //의존관계를 주입
    MemoService memoService; //스프링이 만든 서비스 객체가 연결된다.
    
    
    // 자료를 하기 위해 /memo/list.do페이지에 연결하고, memoService의 리스트 (인터페이스의 추상 메소드를 사용해서 값을 받아온 것들...)을
    // 계층간 데이터 교환을 위해 MemoDTO로 받는다. mav에 출력페이지의 이름과, 아까 받은 memoService.list()가 들어있는 
    // items에 이름을 "list"로 바꾸어서 mav에 저장해 놓는다.
    // 그리고 mav를 리턴한다.
    @RequestMapping("list.do"// <== 사용자가 이런패턴으로 호출하면 밑에 list가 호출된다는 뜻 
    public ModelAndView list(ModelAndView mav) {
        List<MemoDTO> items = memoService.list();   // 메모 리스트 리턴 (Select문 이하~~)
        mav.setViewName("memo/memo_list");            // 출력 페이지의 이름
        mav.addObject("list",items);                // 출력 페이지에 전달할 변수
        return mav;                                    // 페이지로 이동함
    }
    
}
 
cs



MemoServiceImpl.java (메모 서비스 인터페이스 구현 클래스) 중 일부


여기서 MemoDAO는 인터페이스라서 객체를 생성할 수 없지만,

호출이 가능한 이유는 DAO 클래스에서 @Select 어노테이션을 사용해서 @Select ("select * from memo order by idx desc")

사용해 메소드를 생성하였으므로(몸체는 없지만) 객체처럼 완성이 되서, list() 메소드를 호출하면 @Select 쿼리문이 실행이 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example.spring02.service.memo;
 
import java.util.List;
 
import javax.inject.Inject;
 
import org.springframework.stereotype.Service;
 
import com.example.spring02.model.memo.dto.MemoDTO;
 
import com.example.spring02.model.memo.dao.MemoDAO;
 
@Service
public class MemoServiceImpl implements MemoService {
 
    //의존성을 주입해야한다.
    @Inject
    MemoDAO memoDao;
    
    @Override
    //여기서 DAO로 가는 코드를 작성해야 한다.
    public List<MemoDTO> list() {
        return memoDao.list();
    }
cs






  

  Model과 ModelAndView 의 차이점 (예제)


1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping("/board/view")
public ModelAndView view() {
  ModelAndView mv = new ModelAndView();
  mv.addObject("id"30);
  mv.setViewName("board/view"); //뷰를 기술할 필요가 있으므로 리턴타입을 ModelAndView로 하였다.
  return mv;
}
 
@RequestMapping("/board/view")
public String view(Model model) {
  mv.addAttribute("id"30);
  return "board/view"
}
cs


  ModelAndView는 뷰와 모델을 기술할 필요가 있을 때 사용하면 된다.


  Model은 이름 그대로 뷰로 전달할 모델값만 기술 하면 된다.




views -> memo 폴더 생성 -> memo_list.jsp 파일 생성함


view -> include 폴더 생성 -> style.css 파일 생성함



style.css

1
2
3
4
5
@charset "UTF-8";
a:link {text-decoration: none; color:blue; } <!--하이퍼링크 속성에서 밑줄을 제거 색깔은 파란색-->
a:hover {text-decoration: underline; color:red; } <!--마우스 커서가 주소에 닿으면 그때 밑줄이 생기고 색깔은 빨간색-->
a:visited{text-decoration: none;} <!--방문한 링크는 밑줄을 지움-->
a:active{text-decoration: none; color:yellow;<!--클릭했을때의 링크는 밑줄을 지우고 색깔은 노란색으로 한다.-->
cs



header.jsp

1
2
3
4
5
6
7
8
9
10
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!-- 태그라이브러리를 사용하여 코어와 fmt(날짜와 숫자)의 태그를 추가 -->
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<c:set var = "path" value = "${pageContext.request.contextPath }" /<!-- contextPath태그를 자주쓰니까 간단하고, 호출하기 편하게 path로 만들어놓음 -->
 
<!-- html과 css같은 것은 고정적인 요소이기 때문에 이런것들은 리소스설정을 따로 해주어야 인식이 된다. -->
<script src = "http://code.jquery.com/jquery-3.3.1.js"></script<!-- jquery도 많이 쓰기 때문에 링크시켜놓았다. --> 
<link rel = "stylesheet" href="${path}/include/style.css" /<!-- 방금 작성한 stylesheet파일이 실행되게끔 붙여놓았다. -->
 
cs



menu.jsp

1
2
3
4
5
6
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<!-- 다른페이지에 include되는 페이지 -->
<a href = "${path }/memo/list.do">한줄메모장</a> ㅣ
 
cs



Spring02 프로젝트를 실행하면 url에 http://localhost:8090/spring02/ 라고 나오는데 여기서 "/" 가 

아래 HomeController.java (파일중 일부) 에 @RequestMapping에 value에 맵핑되서 아래 로그가 출력이 되게 된다.

그리고 home로 리턴이 된다.


HomeController.java (파일중 일부)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);
        
        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
        
        String formattedDate = dateFormat.format(date);
        
        model.addAttribute("serverTime", formattedDate );
        
        return "home";
    }
    
}
cs



memo_list.jsp (메모 리스트)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<%@include file="../include/header.jsp" %> <!-- header 파일을 include -->
</head>
<body>
<%@ include file = "../include/menu.jsp" %> <!-- menu 파일을 include -->
<h2>한줄 메모장</h2>
 
<form method="post" action="${path }/memo/insert.do"<!-- 글쓰기 폼을 작성 insert.do로 넘김 -->
이름 : <input name = "writer" size = "10" >
메모 : <input name = "memo" size = "40" >
<input type = "submit" value="확인">
</form>
 
<table border = "1" style = "width:500px;"<!-- 메모장 폼을 작성 -->
    <tr>
        <th>번호</th>
        <th>이름</th>
        <th>메모</th>
        <th>날짜</th>
    </tr>
<c:forEach var="row" items="${list }"<!--MemoController에서 넘겨준 items(메모 리스트)를 list라는 이름으로 받음 el문 내부의 이름과
                                        넘긴 변수의 이름이 같아야 한다.-->
    <tr>
        <td>${row.idx }</td>  <!-- row에서 값들을 하나씩 불러온다. -->
        <td>${row.writer }</td>
        <td>${row.memo }</td>
        <td>
        <fmt:formatDate value="${row.post_date}" pattern="yyyy-MM-dd HH:mm:ss" /></td>
    </tr>
</c:forEach>        
</table>
</body>
</html>
cs




:

CSS 기초 문법

Front-End/CSS 2019. 6. 5. 12:20

CSS 사용이유 : HTML만 사용하면 문서의 디자인이 한정적이기 때문에 CSS를 사용한다.

 

-CSS 구문 구성-

 

CSS의 규칙은 선택자(Selector)과 선언 블록(declaration block)으로 구성된다.

(어떤거? (Selector) 를 어떻게? (Declaration) 꾸며줄 것인가?? 라는 의미)

 

 Selector       Declaration     Declaration

 h1  { color : red;   font-size : 10; }

 

위의 예제에서는 <h1> 태그 요소의 글자 색상은 빨간색으로 하고 글자 크기는 10으로 표시하라는 뜻이된다.

 

  
  color <- Property
  red <- Value


  font-size <- Property
  10 <- Value

 

 

첫번째 선택자(Selector) 은 HTML의 <DIV>나 <P> 태그 같은 스타일을 지정할 HTML 태그나 클래스, ID 등을 가리킨다.

(쉽게 말해서 html의 어떤 요소를 꾸며줄건지 선택하는 부분)

 

두번째 선언블록은 하나 이상의 선언의 모음을 말하는데, 블록 안에 각 선언들은 세미콜론 ( ; ) 으로 끝마치거나

구분되고 시작과 끝은 중괄호 ({ })로 둘러싸여진다.

(자세한 속성에 대한 값들.. 예를 들면 색깔이나 높이 등등등... 그리고 선언들이 합쳐진것을 선언블록이라고 한다.)

 

블록안을 살펴보면 개별적인 선언 (declaration)은 속성(Property)과 (Value)으로 구성된다.

속성이란건 어떤 요소에 대한 속성을 말한다.

 

 

-em 단위-

 

em 단위는 상위 요소 크기의 몇 배인지로 크기를 정합니다. 

 

간단한 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!doctype html>
<html lang="ko">
  <head>
    <meta charset="utf-8">
    <title>CSS</title>
    
<style>
html { font-size: 16px; } //html요소의 크기를 16픽셀로 한다
   body { font-size: 1.5em; } //body 요소의 크기를 상위요소 크기의 1.5배인 24픽셀로 한다.
   .a { font-size: 2.0em; } //문단 요소의 크기를 상위요소(body) 크기의 2배인 48픽셀로 한다.
   </style>
 
      
  </head>
  <body>
    <p class="a">Lorem Ipsum Dolor</p>
  </body>
</html>
cs

 

 

 

-rem 단위-

 

rem  단위는 문서의 최상위 요소, 즉 html 요소의 크기의 몇 배인지로 크기를 정합니다. 위 예제에서

 

1
.a { font-size: 2.0em; }
cs

 

에서 단위를 rem으로 바꾸면

 

1
.a { font-size: 2.0rem; }
cs

 

글자 크기는 32픽셀이 됩니다.

(html 요소의 크기가 16픽셀이고 2.0 배를 해주었기 때문에 32픽셀이 된다.)

 

참고로 html 요소와 문단 요소 사이에 있는 body 요소의 크기는 영향을 미치지 않습니다.

 

 

 



  
 -정리-


  CSS는 선택자와 선언모음으로 구성이 되고 각 선언들은 속성과 값으로 구성된다.
 

 

 

 

출처

https://www.youtube.com/watch?v=ujzr0nxWb2E

아래 책은 제가 공부할때 활용했던 책으로 추천드리는 책이니 한번씩 읽어보시는것을 추천드립니다!! ㅎㅎ

토비의 스프링 3.1 세트:스프링의 이해와 원리 + 스프링의 기술과, 에이콘출판

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

'Front-End > CSS' 카테고리의 다른 글

HTML 문서에 CSS를 사용하는 방법들  (0) 2019.08.26
:

AOP(Aspect Oriented Programming) - 인강

Back-End/Spring 2019. 6. 5. 00:07

AOP(Aspect Oriented Programming)


핵심 : 흩어진 코드를 한 곳으로 모아서 코딩


 

 -흩어진 코드-


 class A {    

method a ( ) {            

    AAAA            

    오늘은 7월 4일 미국 독립 기념일이래요.            

    BBBB    

 }      


 method b ( ) {            

    AAAA            

    저는 아침에 운동을 다녀와서 밥먹고 빨래를 했습니다.            

    BBBB    

 }


 class B {   

 method c( ) {           

    AAAA           

    점심은 이거 찍느라 못먹었는데 저녁엔 제육볶음을 먹고 싶네요.              BBBB   

 }





  

 -모아 놓은 AAAA 와 BBBB-


 class A {    

 method a ( ) {            

오늘은 7월 4일 미국 독립 기념일이래요.    

 }      


 method b ( ) {            

저는 아침에 운동을 다녀와서 밥먹고 빨래를 했습니다.    

    } 

 }

  

 class B {   

 method c( ) {           

점심은 이거 찍느라 못먹었는데 저녁엔 제육볶음을 먹고 싶네요.   

    } 

 }


 class AAAABBBB {     

method aaaabbb (JoinPoint point) {          

AAAA   

point.execute( )          

BBBB 

    } 

 }

 



바이트 코드를 조작하는 방법


컴파일 하면 닷(.) 클래스 파일이 생기는데 이 클래스 파일을 조작하는 것

이미 컴파일된 코드 안에 끼워넣는것 AAAA와 BBBB를....




프록시 패턴을 사용하는 방법 (스프링 AOP에서 사용하는 방법!!!!)


A라는 클래스 타입의 객체를 상속을 받아 A-클래스를 만들고, a( ) 메소드 호출후

AAAA라고 나오게끔 하고, b( ) 메소드 호출후 BBBB라고 출력하게함.



 

  프록시 패턴(proxy pattern)은 컴퓨터 프로그래밍에서 소프트웨어 디자인 패턴의 하나이다.

  일반적으로 프록시는 다른 무언가와 이어지는 인터페이스의 역할을 하는 클래스이다. 프록시는 어떠한 것(이를테면 네트워크 연결, 

  메모리 안의 커다란 객체, 파일, 또 복제할 수 없거나 수요가 많은 리소스)과도 인터페이스의 역할을 수행할 수 있다.

  




트랜잭션 처리 예제


 

class A {    

method a ( ) {            

    AAAA                                                // 트랜잭션 매니저를 가지고 트랜잭션을 오토커밋을 false로 하고 밑에 구문 실행          

    오늘은 7월 4일 미국 독립 기념일이래요.   //이 구문은 try~catch로 묶어놓음, catch블럭에서 문제가 생겼을 경우 롤백시킴 

BBBB //그 코드가 AAAA, BBBB처럼 모든코드를 감싼다 

                                                        //오늘은~ 실행하고 커밋을 하면 트랜잭션 처리가 된다.

 }      





OwnerController (컨트롤러)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@Controller
class OwnerController {
 
    private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
    private final OwnerRepository owners;
 
 
    public OwnerController(OwnerRepository clinicService) {
        this.owners = clinicService;
    }
 
    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
        dataBinder.setDisallowedFields("id");
    }
 
    @LogExecutionTime
    @GetMapping("/owners/new")
    public String initCreationForm(Map<String, Object> model) {
        Owner owner = new Owner();
        model.put("owner", owner);
        return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
    }
    @LogExecutionTime
    @PostMapping("/owners/new")
    public String processCreationForm(@Valid Owner owner, BindingResult result) {
        if (result.hasErrors()) {
            return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
        } else {
            this.owners.save(owner);
            return "redirect:/owners/" + owner.getId();
        }
    }
    @LogExecutionTime
    @GetMapping("/owners/find")
    public String initFindForm(Map<String, Object> model) {
        model.put("owner"new Owner());
        return "owners/findOwners";
    }
    @LogExecutionTime
    @GetMapping("/owners")
    public String processFindForm(Owner owner, BindingResult result, Map<String, Object> model) {
 
        // allow parameterless GET request for /owners to return all records
        if (owner.getLastName() == null) {
            owner.setLastName(""); // empty string signifies broadest possible search
        }
 
        // find owners by last name
        Collection<Owner> results = this.owners.findByLastName(owner.getLastName());
        if (results.isEmpty()) {
            // no owners found
            result.rejectValue("lastName""notFound""not found");
            return "owners/findOwners";
        } else if (results.size() == 1) {
            // 1 owner found
            owner = results.iterator().next();
            return "redirect:/owners/" + owner.getId();
        } else {
            // multiple owners found
            model.put("selections", results);
            return "owners/ownersList";
        }
    }
cs

SampleController (컨트롤러)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
public class SampleController {
 
    @Autowired
    String keesun;
 
 
    @LogExecutionTime //아래 구문이 실행되는게 얼마나걸리는지??
    @GetMapping("/context")
    public String context() {
 
        return "hello" + keesun;
    }
}
 
cs


어노테이션만있으면 주석과 같은 기능을 하므로 어노테이션을 처리할 파일을 만들어주어야 한다.
트랜잭션 처리를 어노테이션 하나로 처리할수 있어서 효율적이다.

Logaspect.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package org.springframework.samples.petclinic.aspect;
 
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
 
@Component
@Aspect
public class Logaspect {
 
    Logger logger = LoggerFactory.getLogger(Logaspect.class); //이 클래스에서 얻는 로그를 logger변수에 저장
 
    @Around("@annotation(LogExecutionTime)")
    public Object logExcutionTime(ProceedingJoinPoint joinPoint) throws Throwable
    //스프링이 제공하는 스톱워치를 사용
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
 
        Object ret =  joinPoint.proceed();
 
        stopWatch.stop();
        logger.info(stopWatch.prettyPrint());
 
        return ret;
 
}
 
cs


'Back-End > Spring' 카테고리의 다른 글

스프링 로그 분석  (0) 2019.06.05
Oracle와 mybatis 연동 실습  (0) 2019.06.05
스프링 프로젝트 구조  (0) 2019.06.04
스프링 프레임워크 Inversion of Control (IoC)  (0) 2019.06.03
스프링 프로젝트 살펴보기  (0) 2019.06.02
:

스프링 프로젝트 구조

Back-End/Spring 2019. 6. 4. 11:14

스프링 구조 정리중.xlsx







  

  DAO의 정의


  Data Access Object의 약자로 간단히 Database의 data에 접근을 위한 객체입니다.

  Database에 접근을 하기위한 로직과 비즈니스 로직을 분리하기 위해서 사용을 합니다.
  웹 서버와 DB를 연결할 때 커넥션 객체가 필요한데 이 커넥션 객체를 하나씩 생성하고 삭제하면 너무 자원의
  소모가 심해서 DB에 접속하는 객체를 전용으로 하나만 만들고 모든 페이지에서 그 객체를 호출할수 있게
  해주는 객체가 바로 DAO 객체입니다.




 

  DTO의 정의


  Data Transfer Object의 약자이고, 계층간 데이터 교환을 위한 자바빈즈를 말한다.
  여기서 말하는 계층은 Controller, View, Business Layer, Persistent Layer를 말한다.

  그리고 각 계층간 데이터 교환을 위한 객체를 DTO 또는 VO 라고 부른다.

  일반적인 DTO는 로직을 갖고 있지 않는 순수한 데이터 객체이며 속성과 그 속성에

  접근 하기 위한 getter, setter 메소드만 가진 클래스를 말합니다.




  Service의 정의


  Service의 역할은 DAO가 DB에서 받아온 데이터를 전달받아 가공하는 것이다.




  Controller의 정의


  시스템으로 들어오는 요청과 응답을 담당하는 파일





이렇게 3단계로 package를 설정하는 이유는 기능별로 모듈화 하기 위함이 가장 크다.

모듈화를 하면 계층을 객체 지향적으로 할 수 있고, 유지보수 할 때도 편리하게 사용할 수 있으며 팀 프로젝트를 할 때에도 효율적으로 

역할 분담해서 사용 할 수 있다.


  

  모듈화란??


  프로그래밍 언어로 프로그램을 제작시 생산성과 최적화, 관리에 용이하게 모듈(기능) 단위로 분할하는 것




프로젝트 실행 과정



1. 스프링 프로젝트를 run(서버 구동) 시키면 브라우저에서 클라이언트가 url을 전송한다.


2. Dispatcher Servlet이 그 url을 가로챈다.
3. web.xml에서 스프링의 환경설정 파일(root-context.xml , servlet-context.xml) 을 모두 읽어들여서 (컨트롤러) bean 생성을 해둔다.
4. 들어온 url로 mapping (@RequestMapping 어노테이션을 사용한 클래스) 되어 있는 controller가 있는지 확인 (Handler Mapping)한다.
5. Dispatcher Servlet가 Controller를 불러 요청한 작업을 수행
   controller는 String을 리턴하여 경로를 알려줄 수도 있다.
6. 작업을 수행한 후, ModelAndView를 리턴한다.
7. View Resolver를 통해 controller에서 들어온 view의 이름을 찾는다.
8. 찾은 view를 요청사항 (model)과 함께 송신한다.
결론 : Dispatcher Servlet가 모든것을 제어한다. 이것이 제어의 역전 (Inversion of Control)
         jsp 파일이 아닌 프로젝트 자체를 Run on Server시켜야 처음에 Project가 생성되면서  Dispatcher Servlet가 일을 할 수 있다.




쓰레드 

핸들러 (handler)

컴퓨터 프로그램 수행 시 프로세스 내부에 존재하는 수행경로, 

즉 일련의 실행코드. 프로세스는 단순히 껍데기이고, 

실제 작업은 스레드가 담당한다.

 다른 객체가 보낸 메시지 수신, 처리하는 객체

 서브 스레드가 보낸 메시지를 받아 UI변경을 한다.





출처

https://ryeom2.tistory.com/18?category=767471



Dispatcher-Servlet 이란?


클라이언트로부터 어떠한 요청이 들어오면 Tomcat (톰캣) 과 같은 서블릿 컨테이너가 요청을 받는데 이때 

제일 앞에서 서버로 들어오는 모든 요청을 처리하는 *프론트 컨트롤러를 Spring에서 정의하였고, 이를 

Dispatcher - Servlet이라고 합니다.

그래서 공통처리 작업을 Dispatcher 서블릿이 처리한 후, 적절한 세부 컨트롤러로 작업을 위임해준다.

물론 Dispatcher-Servlet가 처리하는 url 패턴을 지정해주어야 하는데 일반적으로 /*.do 같음..

/로 시작하며 .do로 끝나는 url 패턴에 대해서 처리하라고 지정해줍니다.



Dispatcher-Servlet의 장점


Spring MVC는 Dispatcher Servlet가 등장함에 따라 web.xml의 역할을 상당히 축소시켜주었습니다.

기존에는 모든 서블릿에 대해 URL 매핑을 활용하기 위해서 web.xml에 모두 등록해주어야했지만, dispatcher-servlet가

해당 어플리케이션으로 들어오는 모든 요청을 핸들링해주면서 작업을 상당히 편하게 할 수 있게 되었습니다.








Dispatcher-Servlet의 단점


모든 요청을 처리하다보니 이미지나 HTML 파일을 불러오는 요청마다 전부 Controller로 넘겨버립니다.

게다가 JSP 파일 안의 JavaScript나 StyleCSS 파일들에 대한 요청들 까지도 모두 디스패치 서블릿이 가로채는

까닭에 자원을 불러오지 못하는 상황도 발생하곤 했습니다.

이에 대한 해결책은 두가지가 있는데 첫번째는 클라이언트의 요청을 2가지로 분리하여 구분하는 것입니다.


  1. /apps의 URL로 접근하면 Dispatcher Servlet가 담당한다.


  2. /resources의 URL로 접근하면 Dispatcher Servlet이 컨트롤할 수 없으므로 담당하지 않는다.




이러한 방식은 코드가 지저분해지고, 모든 요청에 대해서 저런 URL을 붙여주기 때문에 직관적인

설계가 될 수 없습니다.

두번째 방법은 모든 요청을 컨트롤러에 등록하는 것인데, 무식한 방법입니다.


가장 유용한 방법은 <mvc:resources /> 를 이용한 방법인데, 이것은 만약 Dispatcher Servlet에서 해당 요청에 대한 컨트롤러를

찾을 수 없는 경우에, 2차적으로 설정된 경로에서 요청을 탐색하여 자원을 찾아내는 것입니다.

이렇게 영역을 분리하면 효율적인 리소스관리를 지원할 뿐 아니라 추후에 확장을 용이하게 해준다는 장점이 있습니다.




:

스프링 프레임워크 Inversion of Control (IoC)

Back-End/Spring 2019. 6. 3. 23:39

spring-petclinic-master.zip



IoC (Inversion of Control)


의존성에 대한 컨트롤이 뒤바뀌는 것을 말한다.

원래 의존성은 자기자신이 가지고 있다.


 

  class OwnerController {

private OwnerRepository repository = new OwnerRepository( );

  }




의존성을 주입


  class OwnerControllerTest{

@Test

public void create( ) {

OwnerRepository repo = new OwnerRepository( );

OwnerController controller = new OwnerController(repo);

  }

  }



servlet의 제어권도 서블릿 자체가 아닌 서블릿 컨테이너가 가지고 있으므로 의존성 주입이라고도

볼 수 있다.



IoC 컨테이너 


자신이 컨테이너 내부에 만든 객체 - 빈(bean)을 만들고 엮어주며 제공해준다.

이러한 빈의 의존성을 관리한다.

코드 옆에 초록색 문양이 붙어있으면 빈(bean) 이다.


빈 설정

 * 이름 또는 ID

 * 타입

 * 스코프


IoC 컨테이너는 직접 쓸 일은 많지 않다.

애플리케이션 컨텍스트는 위 코드에 존재하지 않는다.


ApplicationContext는 빈들을 만들고 의존성을 엮어준다.

빈에다 주입을 해서 사용할 수도 있다.



 

  @RestController = REST 방식(특정한 URI는 반드시 그에 상응하는 데이터 자체라는 것을 의미) 의 데이터 자체를 서비스 하는것을 말한다.


  @Autowired = 스프링이 빈의 요구사항과 매칭되는 애플리케이션 컨텍스트상에서 다른 빈을 찾아 빈 간의 의존성을 

      자동으로 만족시키도록 하는 수단이다.


  @GetMapping = @RequestMapping(method = RequestMethod.GET)의 축양형으로써, 어노테이션만 보고 무슨 메소드 요청인지

   바로 알아볼 수 있다.





 

  @RestController

  public class SampleController {


@Autowired

ApplicationContext applicationContext;


@GetMapping("/context")

public String context( ) {

return "hello" + applicationContext.getBean(OwnerRepository.class);

  }

  }




빈 (Bean)


스프링 IoC 컨테이너가 관리하는 객체


등록하는 방법


 

  @Component


* @Repository

* @Service

* @Controller




또는 직접 일일이 XML이나 자바 설정 파일에 등록함


꺼내쓰는 방법

@Autowired 또는 @Inject

또는 ApplicationContext에서 getBean( )으로 직접 꺼내거나


특징

 "빈"들만 의존성 주입을 해준다.



의존성 주입 (Dependency Injection)


객체 자체가 아니라 Framework에 의해 객체의 의존성이 주입되는 설계 패턴

Framework에 의해 동적으로 주입되므로 여러 객체 간의 결합이 줄어든다.

Dependency Injection은 Spring Framework에서 지원하는 IoC의 형태


 

  @Autowired / @Inject를 붙이는 곳


* 생성자

* 필드

* Setter




'Back-End > Spring' 카테고리의 다른 글

AOP(Aspect Oriented Programming) - 인강  (0) 2019.06.05
스프링 프로젝트 구조  (0) 2019.06.04
스프링 프로젝트 살펴보기  (0) 2019.06.02
스프링 프레임워크 입문  (0) 2019.06.02
Spring를 이용한 회원정보관리  (0) 2019.05.31
:

IntelliJ 스프링 (spring-boot:run 구동) 서버 충돌 (localhost:8080 - 아이디와 비밀번호 요구)

Back-End/Problems 2019. 6. 2. 23:31

IntelliJ 스프링 (spring-boot:run 구동) run하고 localhost:8080 접속시 아이디와 비밀번호를 요구하는 창이 뜨는 문제





오라클 db와 tomcat이 서로 충돌해서 발생하는 문제였음


아래와 같이 오라클 db의 서비스를 중지 시키면 해결 된다.





정상구동 확인



출처

https://aboutprogramming.tistory.com/25

:

스프링 프로젝트 살펴보기

Back-End/Spring 2019. 6. 2. 23:24

-Petclinic 프로젝트-


CRUD 프로젝트 이다.

(Create, Read, Update, Delete)


도메인이 Petclinic이기 때문에 도메인 클래스를 확인.


  전체적인 구조


  오너가 펫을 가지고 있고, 펫은 여러개를 가질수 있고 여러군데의 병원을 방문할 수 있다.

  수의사는 여러가지의 스페셜리스트 (전문)을 가지고 있다.





Owner 중 일부 (owner는 Pet를 여러개 가질수 있다.)

1
2
 @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
    private Set<Pet> pets;
cs



Pet 는 여러가지 type가 있다. (Pet 중 일부) 그리고 Visit로 이동

(펫이 언제 이 병원에 방문할건지 알아야 하기 때문)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public LocalDate getBirthDate() {
        return this.birthDate;
    }
 
    public PetType getType() {
        return this.type;
    }
 
    public void setType(PetType type) {
        this.type = type;
    }
 
    public Owner getOwner() {
        return this.owner;
    }
 
    protected void setOwner(Owner owner) {
        this.owner = owner;
    }
cs



Visit 도메인 (언제??? 에 해당되는 코드를 출력)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
 * Copyright 2012-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.samples.petclinic.visit;
 
import java.time.LocalDate;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.NotEmpty;
 
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.samples.petclinic.model.BaseEntity;
 
/**
 * Simple JavaBean domain object representing a visit.
 *
 * @author Ken Krebs
 * @author Dave Syer
 */
@Entity
@Table(name = "visits")
public class Visit extends BaseEntity {
 
    @Column(name = "visit_date")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate date;
 
    @NotEmpty
    @Column(name = "description")
    private String description;
 
    @Column(name = "pet_id")
    private Integer petId;
 
    /**
     * Creates a new instance of Visit for the current date
     */
    public Visit() {
        this.date = LocalDate.now();
    }
 
    public LocalDate getDate() {
        return this.date;
    }
 
    public void setDate(LocalDate date) {
        this.date = date;
    }
 
    public String getDescription() {
        return this.description;
    }
 
    public void setDescription(String description) {
        this.description = description;
    }
 
    public Integer getPetId() {
        return this.petId;
    }
 
    public void setPetId(Integer petId) {
        this.petId = petId;
    }
 
}
 
cs




Vet (수의사) (어떤 전문인지 알기위해서 Specialty로 이동)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/*
 * Copyright 2012-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.samples.petclinic.vet;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
 
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlElement;
 
import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator;
import org.springframework.samples.petclinic.model.Person;
 
/**
 * Simple JavaBean domain object representing a veterinarian.
 *
 * @author Ken Krebs
 * @author Juergen Hoeller
 * @author Sam Brannen
 * @author Arjen Poutsma
 */
@Entity
@Table(name = "vets")
public class Vet extends Person {
 
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), inverseJoinColumns = @JoinColumn(name = "specialty_id"))
    private Set<Specialty> specialties; //어떤쪽의 스페셜리스트 인지?? (전문인지)
 
    protected Set<Specialty> getSpecialtiesInternal() {
        if (this.specialties == null) {
            this.specialties = new HashSet<>();
        }
        return this.specialties;
    }
 
    protected void setSpecialtiesInternal(Set<Specialty> specialties) {
        this.specialties = specialties;
    }
 
    @XmlElement
    public List<Specialty> getSpecialties() {
        List<Specialty> sortedSpecs = new ArrayList<>(getSpecialtiesInternal());
        PropertyComparator.sort(sortedSpecs,
                new MutableSortDefinition("name"truetrue));
        return Collections.unmodifiableList(sortedSpecs);
    }
 
    public int getNrOfSpecialties() {
        return getSpecialtiesInternal().size();
    }
 
    public void addSpecialty(Specialty specialty) {
        getSpecialtiesInternal().add(specialty);
    }
 
}
 
cs



Specialty (어느쪽의 전문인지 표시)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * Copyright 2012-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.samples.petclinic.vet;
 
import java.io.Serializable;
 
import javax.persistence.Entity;
import javax.persistence.Table;
 
import org.springframework.samples.petclinic.model.NamedEntity;
 
/**
 * Models a {@link Vet Vet's} specialty (for example, dentistry).
 *
 * @author Juergen Hoeller
 */
@Entity
@Table(name = "specialties")
public class Specialty extends NamedEntity implements Serializable {
 
}
 
cs




data.sql (쿼리문이 이미 들어가있음)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
INSERT INTO vets VALUES (1'James''Carter');
INSERT INTO vets VALUES (2'Helen''Leary');
INSERT INTO vets VALUES (3'Linda''Douglas');
INSERT INTO vets VALUES (4'Rafael''Ortega');
INSERT INTO vets VALUES (5'Henry''Stevens');
INSERT INTO vets VALUES (6'Sharon''Jenkins');
 
INSERT INTO specialties VALUES (1'radiology');
INSERT INTO specialties VALUES (2'surgery');
INSERT INTO specialties VALUES (3'dentistry');
 
INSERT INTO vet_specialties VALUES (21);
INSERT INTO vet_specialties VALUES (32);
INSERT INTO vet_specialties VALUES (33);
INSERT INTO vet_specialties VALUES (42);
INSERT INTO vet_specialties VALUES (51);
 
INSERT INTO types VALUES (1'cat');
INSERT INTO types VALUES (2'dog');
INSERT INTO types VALUES (3'lizard');
INSERT INTO types VALUES (4'snake');
INSERT INTO types VALUES (5'bird');
INSERT INTO types VALUES (6'hamster');
 
INSERT INTO owners VALUES (1'George''Franklin''110 W. Liberty St.''Madison''6085551023');
INSERT INTO owners VALUES (2'Betty''Davis''638 Cardinal Ave.''Sun Prairie''6085551749');
INSERT INTO owners VALUES (3'Eduardo''Rodriquez''2693 Commerce St.''McFarland''6085558763');
INSERT INTO owners VALUES (4'Harold''Davis''563 Friendly St.''Windsor''6085553198');
INSERT INTO owners VALUES (5'Peter''McTavish''2387 S. Fair Way''Madison''6085552765');
INSERT INTO owners VALUES (6'Jean''Coleman''105 N. Lake St.''Monona''6085552654');
INSERT INTO owners VALUES (7'Jeff''Black''1450 Oak Blvd.''Monona''6085555387');
INSERT INTO owners VALUES (8'Maria''Escobito''345 Maple St.''Madison''6085557683');
INSERT INTO owners VALUES (9'David''Schroeder''2749 Blackhawk Trail''Madison''6085559435');
INSERT INTO owners VALUES (10'Carlos''Estaban''2335 Independence La.''Waunakee''6085555487');
 
INSERT INTO pets VALUES (1'Leo''2010-09-07'11);
INSERT INTO pets VALUES (2'Basil''2012-08-06'62);
INSERT INTO pets VALUES (3'Rosy''2011-04-17'23);
INSERT INTO pets VALUES (4'Jewel''2010-03-07'23);
INSERT INTO pets VALUES (5'Iggy''2010-11-30'34);
INSERT INTO pets VALUES (6'George''2010-01-20'45);
INSERT INTO pets VALUES (7'Samantha''2012-09-04'16);
INSERT INTO pets VALUES (8'Max''2012-09-04'16);
INSERT INTO pets VALUES (9'Lucky''2011-08-06'57);
INSERT INTO pets VALUES (10'Mulligan''2007-02-24'28);
INSERT INTO pets VALUES (11'Freddy''2010-03-09'59);
INSERT INTO pets VALUES (12'Lucky''2010-06-24'210);
INSERT INTO pets VALUES (13'Sly''2012-06-08'110);
 
INSERT INTO visits VALUES (17'2013-01-01''rabies shot');
INSERT INTO visits VALUES (28'2013-01-02''rabies shot');
INSERT INTO visits VALUES (38'2013-01-03''neutered');
INSERT INTO visits VALUES (47'2013-01-04''spayed');
 
cs


:

IntelliJ IDEA (에러 : Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.4.RELEASE:run)

Back-End/Problems 2019. 6. 2. 22:55

  

  [ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.4.RELEASE:run (default-cli) on project spring-petclinic:    Could not exec java: Application finished with exit code: 1 -> [Help 1]

  [ERROR] 

  [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.

  [ERROR] Re-run Maven using the -X switch to enable full debug logging.

  [ERROR] 

  [ERROR] For more information about the errors and possible solutions, please read the following articles:

  [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException



[오류] 목표 org.springframework.boot를 실행하지 못했습니다 : spring-boot-maven-plugin : 2.1.4.RELEASE : 프로젝트에서 실행 (default-cli) spring-petclinic : exec java : 종료 코드로 끝난 응용 프로그램 : 1 -> [도움말 1]



검색해도 해결법이 나오지 않아서 IntelliJ를 종료후 재시작 후 reimport 하여 해결함


: