2021년 12월 4일 토요일

(스프링게시판, JPA게시판소스)Spring Data JPA, 스프링부트(Spring Boot) 게시판 실습

 (스프링게시판, JPA게시판소스)Spring Data JPA, 스프링부트(Spring Boot) 게시판 실습

 



https://www.youtube.com/watch?v=PKO-e2mgQfc&list=PLxU-iZCqT52AlV-Y7UlwSQp8N6pMjijFX&index=16&t=182s 

https://www.youtube.com/watch?v=sgJUROeXIWg&list=PLxU-iZCqT52AlV-Y7UlwSQp8N6pMjijFX&index=17&t=2s 

4-9. Spring Data JPA, Spring Boot, 게시판 실습

4-9-1. 구현 기술 및 기능

 

  • Spring Boot, MVC, Spring Data JPA, AngularJS 기반으로 게시판을 만들어 보자.
  • JPA로 게시판을 만든다는 것은 맞지 않을 수도 있지만 기능과 사용방법을 익힌다는 관점에서 간단히 만들어 보자. 본예제는 오라클 DB를 기준으로 작성되었으며  MySQL(MariaDB) 예제는 다음 URL에서 참조하면 된다.

 

http://ojc.asia/bbs/board.php?bo_table=LecJpa&wr_id=244

 

  • 구현기술

Spring Boot, Spring WEB MVC, RestController

Spring Data JPA(Hibernate)

기본 JpaRepository

Query Method

Oracle DataBase(DB는 편한걸로 사용가능)

UI : JSP, BootStrap, AngularJS, JSON

Logging: DriverSpy

 

  • 기본기능

글리스트 보기, 글입력, 글읽기, 글수정, 글삭제, 답변글작성

 

  • 테이블 및 시퀀스 DDL

 

  • 테이블 및 시퀀스는 엔티티를 정의해서 자동 생성시킬 예정이니 DB쪽에 생성할 필요없다. 구조만 확인하자.
  • Board 테이블의 PK(ID칼럼, Primary Key)는 오라클 시퀀스를 이용할 것이다. MySQL이라면 자동증분 칼럼을 사용하니 특별히 생성할 필요 없다.(본 예제는 오라클을 기준으로 한다.) 
  • 엔티티를 만들 때 키 부분(ID칼럼)에 어노테이션 사용하는 것만 DB가 무엇이냐에 따라 좀 다르니 확인하면 된다.

 

JPA에서 자동 생성된 DDL 스크립트는 다음과 같다.


create table board (

   id number(10,0) not null, 

   content varchar2(4000 char) not null, 

   name varchar2(20 char) not null, 

   passwd varchar2(20 char) not null, 

   readcount number(5) default 0 not null, 

   regdate date default sysdate not null, 

-- 답변인경우 어느글의 답변인지 상위글 번호,최상위글인 경우 자신의 글번호 동일,

-- 리스트보기에서 정렬시 우선  reply로 우선하게 된다.

   reply number(5) not null, 

-- 하나의 글 아래에 생기는 모든 답변들에 대해 순차적으로 1씩 증가(reply_level과 관계없이)

   replylevel number(5) default 0 not null, 

-- 1차,2차 답글인지 여부, 글에  답변이 두개면 그 두답변은 reply_level이 같다. 

-- 리스트보기에서 reply_level에 따라 들여쓰기를 한다.    

   replystep number(5) default 0 not null, 

   title varchar2(500 char) not null, 

   primary key (id)

)


create sequence BOARD_SEQ;

 

4-9-2 프로젝트 생성 및 메이븐, 로깅, 오라클 위한 설정

 

STS -> Spring Starter Project

   Name : jpaboard

   Group : ojc.asia

   Artifact : jpaboard

   Description : Spring Data JPA Board

   pckage : jpa.board 입력


다음 창에서

Core : Lombok

SQL : JPA

Web : Web 선택


롬복(Lombok)설치는 다음 URL 참조

http://ojc.asia/bbs/board.php?bo_table=LecSpring&wr_id=561


 

 



  • pom.xml에 로깅을 위한 DriverSpy 및 오라클DB를 사용하기 위한 설정을 추가한다.

 

[pom.xml]

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

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>


<groupId>ojc.asia</groupId>

<artifactId>jpaboard</artifactId>

<version>1.0-SNAPSHOT</version>

<packaging>jar</packaging>


<name>jpaboard</name>

<description>Spring Data JPA Board</description>


<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.3.3.RELEASE</version>

<relativePath/> <!-- lookup parent from repository -->

</parent>


<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<java.version>1.8</java.version>

</properties>


<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jpa</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>


<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>


<!--  JSP, JSTL 사용위해 -->

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>jstl</artifactId>

</dependency>

<dependency>

<groupId>org.apache.tomcat.embed</groupId>

<artifactId>tomcat-embed-jasper</artifactId>

<scope>provided</scope>

</dependency>


<!-- DriverSpy -->

<dependency>

<groupId>org.bgee.log4jdbc-log4j2</groupId>

<artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>

<version>1.16</version>

</dependency>


<!-- for oracle -->

<dependency>

<groupId>com.oracle</groupId>

<artifactId>ojdbc6</artifactId>

<version>11.1.0.7.0</version>

</dependency>



</dependencies>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

<repositories>

<repository>

<id>codelds</id>

<url>https://code.lds.org/nexus/content/groups/main-repo;

</repository>

</repositories>

</project>



[src/main/resources/application.properties]

spring.datasource.platform=oracle

spring.datasource.sql-script-encoding=UTF-8

spring.datasource.url=jdbc:log4jdbc:oracle:thin:@192.168.0.27:1521:onj

spring.datasource.username=test

spring.datasource.password=test

#spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver

spring.datasource.driver-class-name = net.sf.log4jdbc.sql.jdbcapi.DriverSpy

spring.jpa.show-sql=true

spring.jpa.hibernate.ddl-auto=update


#hibernate config

spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect

logging.level.jpa=DEBUG


#view

spring.mvc.view.prefix=/jsp/

spring.mvc.view.suffix=.jsp

 

[src/main/resources/ log4jdbc.log4j2.properties]

log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator

log4jdbc.dump.sql.maxlinelength=0

 

[src/main/resources/ logback.xml]

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

<configuration>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">    

    <encoder>

      <pattern>%d{yyyyMMdd HH:mm:ss.SSS} [%thread] %-3level %logger{5} - %msg %n</pattern>

    </encoder>

  </appender>

  

  <logger name="jdbc" level="OFF"/>

  

  <logger name="jdbc.sqlonly" level="DEBUG" additivity="false">>

    <appender-ref ref="STDOUT" />

  </logger>

  

  <logger name="jdbc.sqltiming" level="INFO" additivity="false">>

    <appender-ref ref="STDOUT" />

  </logger>   

  

  <logger name="jdbc.resultsettable" level="DEBUG" additivity="false">> 

    <appender-ref ref="STDOUT" />

  </logger>  

  

  <root level="INFO">

    <appender-ref ref="STDOUT" />

  </root>  

</configuration>

 

  • 프로젝트에서 마우스 우측버튼, Maven -> Update Project





























4-9-3 도메인 모델 객체 생성하기

 

  • Jpa.board.model 패키지를 생성 후 엔티티 클래스를 만들자.

 

[Board.java]

 

package jpa.board.model;


import java.util.Date;

import java.util.List;


import javax.persistence.CascadeType;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.FetchType;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.PrePersist;

import javax.persistence.SequenceGenerator;

import javax.persistence.Temporal;

import javax.persistence.TemporalType;


import lombok.Getter;

import lombok.Setter;



@Entity

@Getter

@Setter

// 시퀀스의 시작값은 1

// 시퀀스의 기본 allocationSize는50, 번호가 50부터 생기므로 1로

@SequenceGenerator(name="BOARD_SEQ_GENERATOR",

                   sequenceName="BOARD_SEQ", 

                   initialValue=1,

                   allocationSize=1)  

public class Board {


//  MySQL이라면 아래와같이 기술한다.

// @Id

// @GeneratedValue

// @Column(length=10)

// protected Integer id;


@Id

@GeneratedValue(strategy=GenerationType.SEQUENCE,

                generator="BOARD_SEQ_GENERATOR")

@Column(length=10)

protected Integer id;


@Column(length=20, nullable=false)

protected String name;


@Column(length=20, nullable=false)

protected String passwd;


@Column(length=500, nullable=false)

protected String title;


@Column(length=4000, nullable=false)

protected String content;


//날짜기본형식 time, day, month, year 형태저장

@Column(nullable=false, columnDefinition = "date default sysdate")

@Temporal(TemporalType.TIMESTAMP)

protected Date regdate = new Date();


@Column(nullable=false, columnDefinition = "number(5) default 0")

protected Integer readcount = 0;


// 답변인경우 어느글의 답변인지 상위글번호

// 최상위글인 경우 자신의 글번호 동일하다.

// 리스트보기에서 정렬시 우선적으로 reply로 정렬

@Column(nullable=false, columnDefinition = "number(5)")

protected Integer reply = 0 ;


// 글아래 모든 답변들에 대해 reply_level과 관계없이 1씩 증가    

@Column(nullable=false, columnDefinition = "number(5) default 0")

protected Integer replystep = 0;


// 1차,2차 답글인지 여부

// 하나의 글에 답변이 두개면 그 두답변은 reply_level이 같다. 

// 리스트보기에서 reply_level에 따라 들여쓰기를 한다. 

@Column(nullable=false,columnDefinition = "number(5) default 0", length=10)

protected Integer replylevel = 0;

}

 

  • 프로젝트에서 마우스 우측버튼 -> Run As -> Spring Boot App로 실행 후 오라클쪽에 테이블이 생성되는 것을 확인하자.



























4-9-4. 게시판 리스트보기

 

  • Spring JDBC 또는 MyBatis로 만들 때 보다 쉽고 빠르게 작성할 수 있다. 
  • 스프링 컨트롤러는 RestController를 적용 했으며, 뷰 페이지에 Bootstrap 및 AngulerJS 적용했다.
  • 프로젝트 전체 구조는 다음과 같다.

 

 

[BoardRepository.java]

 

  • 기본적으로 제공하는 JpaRepository를 상속받아 만들면 된다. 
  • JpaRepository는 PagingAndSortingRepository를 상속받았고 PagingAndSortingRepository는 CrudRepository(기본적인 CRUD 기능을 제공한다)를 상속 받았으며 다시 CrudRepository는 Repository 인터페이스를 상속받았다. 
  • 그러므로 JpaRepository는 모든 기능을 다 사용할 수 있고 추가적으로 영속성 컨텍스트에 flush하거나 엔티티를 배치로 삭제할 수 있다. 
  • 기본 기능만으로도 게시판 기능을 구현할 수 있으므로 JpaRepository를 상속 받자.

 

package jpa.board.repository;


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


import jpa.board.model.Board;


public interface BoardRepository extends JpaRepository<Board, Integer> {


}



  • 서비스쪽 클래스를 작성하자.

 

[BoardService.java]

package jpa.board.service;


import org.springframework.data.domain.Page;


import jpa.board.model.Board;


public interface BoardService {

//게시판 리스트 보기

public Page<Board> findAll(Integer curPage);

}

 

  • JpaRepository의 findAll() 메소드를 호출만 하면 되는데 페이징 기능을 구현하기 위해 PageRequest를 만들고 이를 findAll() 메소드의 인자로 넣어주면 된다.

 

  • Board 테이블에서 정렬한 칼럼이 두개 이상이므로 Sort 를 new하면서 Order를 필요한 만큼 생성해주면 되고 ASC는 오름차순, DESC는 내림차순, 그뒤의 문자열은 Board 엔티티의 속성이다. 

 

[BoardServiceImpl.java]

package jpa.board.service;


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

import org.springframework.data.domain.Page;

import org.springframework.data.domain.PageRequest;

import org.springframework.data.domain.Sort;

import org.springframework.data.domain.Sort.Direction;

import org.springframework.data.domain.Sort.Order;

import org.springframework.stereotype.Service;


import jpa.board.model.Board;

import jpa.board.repository.BoardRepository;


@Service

public class BoardServiceImpl implements BoardService {


@Autowired

BoardRepository boardRepository;


@Override

//-----------------------------------------

// 게시판 리스트 보기, 한페이지에 3개씩

// curPage:요청하는 페이지, 첫페이지는 0

//-----------------------------------------

public Page<Board> findAll(Integer curPage) {

PageRequest pr = new PageRequest(curPage, 3, 

                    new Sort(

                    new Order(Direction.DESC, "reply"),

                    new Order(Direction.ASC, "replystep")));

return boardRepository.findAll(pr);

}


}



  • 컨트롤러를 작성하자.

 

[BoardController.java]


package jpa.board.controller;

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

import org.springframework.data.domain.Page;

import org.springframework.data.domain.Pageable;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;


import jpa.board.model.Board;

import jpa.board.service.BoardService;


@RestController

@RequestMapping("/board")

public class BoardController {


@Autowired

BoardService boardService;


//---------------------------------------------

// 루트요청(localhost:8080/board/)시 리스트 보기로 

//---------------------------------------------

@RequestMapping(method = RequestMethod.GET)

public ModelAndView index() {

//jsp아래 board.jsp 호출

return new ModelAndView("board");  

}


//---------------------------------------------

// 게시판 리스트 보기

//---------------------------------------------

@RequestMapping(value="/{curPage}", method = RequestMethod.GET)

public ResponseEntity<Page<Board>> list(Model model, Pageable pageable, @PathVariable Integer curPage) {

Page<Board> page = boardService.findAll(curPage);

return new ResponseEntity<Page<Board>>(page, HttpStatus.OK);

}

}




  • src/main/webapp/js , src/main/webapp/jsp 폴더를 만들고 app.js, board_controller.js, board_service.js, list.jsp를 만들자.

 

[src/main/webapp/js /app.js]

'use strict';

 var App = angular.module('myBoard',[]);

 

[src/main/webapp/js/board_service.js]

'use strict';

App.factory('BoardService', ['$http', '$q', function($http, $q){

 

    return {

         

             list: function(curPage) {

                    return $http.get('http://localhost:8080/board/' +  curPage)

                            .then(

                                    function(response){

                                     console.log("[service:list]server call  suceeded.");

                                        return response.data;

                                    }, 

                                    function(errResponse){

                                        console.error('Error while fetching contents');

                                        return $q.reject(errResponse);

                                    }

                            );

            }

     }; 

}]);

 

[src/main/webapp/js /board_controller.js]

'use strict';


App.controller('BoardController', ['$scope', 'BoardService', 

      function($scope, BoardService) {

          var self = this;

          self.board={id:null,name:'',passwd:'',title:'',content:''};

          self.page=[];

               

          //리스트 보기

          self.list = function(curPage){

              BoardService.list(curPage)

              .then(

                 function(data) {

                     self.page = data;

                     console.log("[controller:list]", self.page);

                     //alert("목록보기 성공!");

                 },

                 function(errResponse){

                     console.error('Error while fetching page...');

                 }

              );

          };           

          self.list(0);

}]);

 

 [board.jsp]

<%@ page contentType="text/html; charset=utf-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>


<html>

<head>

<title>Spring JPA 게시판</title>


<link rel="stylesheet"

href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">


<style>

.name.ng-valid {

background-color: lightgreen;

}


.name.ng-dirty.ng-invalid-required {

background-color: red;

}


.name.ng-dirty.ng-invalid-maxlength {

background-color: yellow;

}


.passwd.ng-valid {

background-color: lightgreen;

}


.passwd.ng-dirty.ng-invalid-required {

background-color: red;

}


.passwd.ng-dirty.ng-invalid-maxlength {

background-color: yellow;

}


.title.ng-valid {

background-color: lightgreen;

}


.title.ng-dirty.ng-invalid-required {

background-color: red;

}


.title.ng-dirty.ng-invalid-maxlength {

background-color: yellow;

}


body, #mainWrapper {

height: 70%;

background-color: rgb(245, 245, 245);

}


body, .form-control {

font-size: 12px !important;

}


.floatRight {

float: right;

margin-right: 18px;

}


.has-error {

color: red;

}


.formcontainer {

background-color: #DAE8E8;

padding: 20px;

}


.tablecontainer {

padding-left: 20px;

}


.generic-container {

width: 80%;

margin-left: 20px;

margin-top: 20px;

margin-bottom: 20px;

padding: 20px;

background-color: #EAE7E7;

border: 1px solid #ddd;

border-radius: 4px;

box-shadow: 0 0 30px black;

}


.custom-width {

width: 80px !important;

}

.pointer {

    cursor: pointer;

}

</style>


<!--  For AngularJS -->

<script

src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js"></script>

<script src="<c:url value='/js/app.js' />"></script>

<script src="<c:url value='/js/board_service.js' />"></script>

<script src="<c:url value='/js/board_controller.js' />"></script>

</head>

<body ng-app="myBoard" class="ng-cloak" ng-controller="BoardController as ctrl">

<div class="generic-container" ng-controller="BoardController as ctrl"

style="width: 800px;">

<div class="panel panel-default">

<div class="panel-heading">

<span class="lead">Spring Data JPA 게시판 글 쓰기 </span>

</div>

<div class="formcontainer">

<form ng-submit="ctrl.submit()" name="myForm" class="form-horizontal">

<input type="hidden" ng-model="ctrl.board.id" />

<div class="row">

<div class="form-group col-md-6">

<label class="col-md-2 control-lable" for="name">Name : </label>

<div class="col-md-7">

<input type="text" ng-model="ctrl.board.name" id="name"

class="name form-control input-sm"

placeholder="Enter your Name" required 

ng-maxlength="20" />

<div class="has-error" ng-show="myForm.$dirty">

<span ng-show="myForm.name.$error.required">This is a

required field</span> <span ng-show="myForm.name.$error.maxlength">Maximum

length is 20</span> <span ng-show="myForm.name.$invalid">This

field is invalid </span>

</div>

</div>

</div>

</div>


<div class="row">

<div class="form-group col-md-6">

<label class="col-md-2 control-lable" for="passwd">Password

:</label>

<div class="col-md-7">

<input type="password" ng-model="ctrl.board.passwd" id="passwd"

class="passwd form-control input-sm"

placeholder="Enter your Password" required ng-maxlength="20" />

<div class="has-error" ng-show="myForm.$dirty">

<span ng-show="myForm.passwd.$error.required">This is a

required field</span> <span ng-show="myForm.passwd.$error.maxlength">Maximum

length is 20</span> <span ng-show="myForm.passwd.$invalid">This

field is invalid </span>

</div>

</div>

</div>

</div>


<div class="row">

<div class="form-group col-md-6">

<label class="col-md-2 control-lable" for="title">Title :</label>

<div class="col-md-7">

<input type="text" ng-model="ctrl.board.title" id="title"

class="title form-control input-sm"

placeholder="Enter your Title" required />

<div class="has-error" ng-show="myForm.$dirty">

<span ng-show="myForm.title.$error.required">This is a

required field</span> <span ng-show="myForm.title.$invalid">This

field is invalid </span>

</div>

</div>

</div>

</div>


<div class="row">

<div class="form-group col-md-6">

<label class="col-md-2 control-lable" for="content">Contents

:</label>

<div class="col-md-7">

<textarea rows="4"

ng-model="ctrl.board.content" id="content"

class="content form-control input-sm"

placeholder="Enter your Contents" required >

</textarea>

<div class="has-error" ng-show="myForm.$dirty">

<span ng-show="myForm.content.$error.required">This is a

required field</span> <span ng-show="myForm.content.$invalid">This

field is invalid </span>

</div>

</div>

</div>

</div>


<div class="row">

<div class="form-actions floatRight">

<input type="submit"

value="{{!ctrl.board.id ? 'Add' : 'Update'}}"

class="btn btn-primary btn-sm" ng-disabled="myForm.$invalid">

<button type="button" ng-click="ctrl.reset()"

class="btn btn-warning btn-sm" ng-disabled="myForm.$pristine">Reset

Form</button>

</div>

</div>

</form>

</div>

</div>

<div class="panel panel-default" style="float: center;">

<div class="panel-heading">

<span class="lead">Spring Data JPA 게시판 리스트보기 </span>

</div>

<h5>

총 {{ctrl.page.totalElements}}</span>건

</h5>

<div class="tablecontainer">

<table width="600" border="1" align="left" class="table table-hover">

<tr align="left">

<th align="center">순번</th>

<th align="center">글번호</th>

<th align="center">제목</th>

<th align="center">글쓴이</th>

<th align="center">등록일</th>

<th align="center">조회수</th>

<th align="center">조회/삭제</th>

</tr>


<tr data-ng-repeat="board in ctrl.page.content">

<td align="center"><span ng-bind="{{$index+1}}"></span></td>

<td align="center"><span ng-bind="board.id"></span></td>

<td align="left">

<!-- 레벨의 수만큼 글을 뒤로 민다 --> <span

ng-repeat="n in [].constructor(board.replylevel) track by $index">

&nbsp;&nbsp; </span> <span ng-bind="board.title"></span>

</td>

<td align="center"><span ng-bind="board.name"></span></td>

<td align="center">{{board.regdate | date:"yy.MM.dd hh:mm"}}</td>

<td align="center"><span ng-bind="board.readcount"></span></td>

<td>

<button type="button" ng-click="ctrl.edit(board.id)"

class="btn btn-success custom-width">Edit</button>

<button type="button" ng-click="ctrl.remove(board.id)"

class="btn btn-danger custom-width">Remove</button>

</td>

</tr>

</tbody>

</table>

<div>

    <!--  게시판 페이징 -->

<ul class="pagination">

<li ng-class="{disabled: ctrl.page.number === 0}"><a

ng-show="ctrl.page.number !== 0" 

class="pointer"

ng-click="ctrl.list(ctrl.page.number-1)">Prev</a>

<span ng-show="ctrl.page.number === 0">Prev</span></li>

<li ng-class="{disabled: ctrl.page.number === ctrl.page.totalPages - 1}">

<a ng-show="ctrl.page.number !== ctrl.page.totalPages - 1"

class="pointer"

ng-click="ctrl.list(ctrl.page.number+1)">Next</a> 

<span ng-show="ctrl.page.number === ctrl.page.totalPages - 1">Next</span>

</li>

</ul>

</div>

</div>

</div>

</div>


</body>

</html>

 

[JpaboardApplication.java] – 스프링 부트 메인


package jpa.board;


import java.util.Date;


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

import org.springframework.boot.CommandLineRunner;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;


import jpa.board.model.Board;

import jpa.board.repository.BoardRepository;


@SpringBootApplication

public class JpaboardApplication implements CommandLineRunner{


@Autowired

BoardRepository boardRepository;


public static void main(String[] args) {

SpringApplication.run(JpaboardApplication.class, args);

}


public void run(String...args) {

//테스트를 위해 글9개 입력

Board b1 = new Board();

b1.setContent("JPA강좌 추천해 주세요1~");

b1.setName("홍길동1"); b1.setPasswd("1111");

b1.setReadcount(0); b1.setRegdate(new Date());

b1.setReply(1); b1.setReplylevel(0);

b1.setReplystep(0); b1.setTitle("강좌추천요망1");


boardRepository.save(b1);


Board b2 = new Board();

b2.setContent("JPA강좌 추천해 주세요2~");

b2.setName("홍길동2"); b2.setPasswd("1111");

b2.setReadcount(0); b2.setRegdate(new Date());

b2.setReply(2); b2.setReplylevel(0);

b2.setReplystep(0); b2.setTitle("강좌추천요망2");


boardRepository.save(b2);


Board b3 = new Board();

b3.setContent("JPA강좌 추천해 주세요3~");

b3.setName("홍길동3"); b3.setPasswd("1111");

b3.setReadcount(0); b3.setRegdate(new Date());

b3.setReply(3); b3.setReplylevel(0);

b3.setReplystep(0); b3.setTitle("강좌추천요망3");


boardRepository.save(b3);


Board b4 = new Board();

b4.setContent("OJC로 가세요...");

b4.setName("홍길동4"); b4.setPasswd("1111");

b4.setReadcount(0); b4.setRegdate(new Date());

b4.setReply(6); b4.setReplylevel(1);

b4.setReplystep(1); b4.setTitle("[답변]강좌추천요망6");


boardRepository.save(b4);


Board b5 = new Board();

b5.setContent("OJC로 가세요...");

b5.setName("홍길동5"); b5.setPasswd("1111");

b5.setReadcount(0); b5.setRegdate(new Date());

b5.setReply(2); b5.setReplylevel(1);

b5.setReplystep(1); b5.setTitle("[답변]강좌추천요망2");


boardRepository.save(b5);


Board b6 = new Board();

b6.setContent("JPA강좌 추천해 주세요6~");

b6.setName("홍길동6"); b6.setPasswd("1111");

b6.setReadcount(0); b6.setRegdate(new Date());

b6.setReply(6); b6.setReplylevel(0);

b6.setReplystep(0); b6.setTitle("강좌추천요망6");


boardRepository.save(b6);


Board b7 = new Board();

b7.setContent("JPA강좌 추천해 주세요7~");

b7.setName("홍길동7"); b7.setPasswd("1111");

b7.setReadcount(0); b7.setRegdate(new Date());

b7.setReply(7); b7.setReplylevel(0);

b7.setReplystep(0); b7.setTitle("강좌추천요망7");


boardRepository.save(b7);


Board b8 = new Board();

b8.setContent("OJC로 가세요...");

b8.setName("홍길동8"); b8.setPasswd("1111");

b8.setReadcount(0); b8.setRegdate(new Date());

b8.setReply(7); b8.setReplylevel(1);

b8.setReplystep(1); b8.setTitle("[답변]강좌추천요망7");


boardRepository.save(b8);


Board b9 = new Board();

b9.setContent("JPA강좌 추천해 주세요9~");

b9.setName("홍길동9"); b9.setPasswd("1111");

b9.setReadcount(0); b9.setRegdate(new Date());

b9.setReply(9); b9.setReplylevel(0);

b9.setReplystep(0); b9.setTitle("강좌추천요망9");


boardRepository.save(b9);


}

}















4-9-5. 게시판 글쓰기

 

  • 게시판 테이블(BOARD)의 reply 칼럼은 NOT NULL 칼럼으로 답변글인 경우 상위 글번호, 아닌 경우 자기 게시물의 ID 값을 가진다. BOARD 테이블의 ID 칼럼이 시퀀스를 이용하여 DB쪽에서 값이 자동생성 되므로 reply 칼럼의 기본값을 id로 설정하는 것이 @Column으로는 불가능 하여 @PostPersist 어노테이션을 사용하여 영속성 컨텍스트에 적재된 후 id 값을 reply에 대입해주면 된다. 

 

 [Board.java 추가]


//-------------------------------------------------------

// 영속성 컨텍스트에 저장 후 id값을 reply에 대입

//-------------------------------------------------------

@PostPersist

public void onCreate() {

reply = id;

}



 [BoardController.java 추가]


//---------------------------------------------

// 게시판 글 쓰기

//---------------------------------------------

@RequestMapping(value="/", method = RequestMethod.POST)

public ResponseEntity<Void> save(@RequestBody Board board) {

boardService.create(board);

return new ResponseEntity<Void>(HttpStatus.CREATED);

}





[BoardService.java 추가]

//글쓰기

public void create(Board board);

 

[BoardServiceImpl.java 추가]

@Override

//-----------------------------------------

// 글 쓰기

//-----------------------------------------

public void create(Board board) {

boardRepository.save(board);

}

 

[board_controller.js]

'use strict';


App.controller('BoardController', ['$scope', 'BoardService', 

      function($scope, BoardService) {

          var self = this;

          self.board={id:null, name:'',passwd:'',title:'',content:''};

          self.page=[];

               

          //리스트 보기

          self.list = function(curPage){

              BoardService.list(curPage)

              .then(

                 function(data) {

                     self.page = data;

                     console.log("[controller:list]", self.page);

                     //alert("목록보기 성공!");

                 },

                 function(errResponse){

                     console.error('Error while fetching page...');

                 }

              );

          };   

          

          //글 입력

          self.create = function(board) {

              BoardService.create(board)

              .then(

                  function() {

                   alert("Save OK!");

                   self.list(0);

                  }, 

                  function(errResponse){

                     console.error('Error while creating Article.');

                  } 

               );    

           }; 

                     

          // ADD or UPDATE 버튼 클릭

          self.submit = function() {

              if(self.board.id===null){                      

                  self.create(self.board);          

                  console.log("[controller:create]", self.board);

              }else{

                  //self.update(self.board, self.board.id);

                  console.log('Article updated with id ', self.board.id);

              }

              self.reset();              

          };   


          self.reset = function(){

           self.board={id:null, name:'',passwd:'',title:'',content:''};

              $scope.myForm.$setPristine(); //reset Form

          };

          

}]);

 

[board_service.js]

'use strict';

 

App.factory('BoardService', ['$http', '$q', function($http, $q){

 

    return {

         

            list: function(curPage) {

                    return $http.get('http://localhost:8080/board/' +  curPage)

                            .then(

                                    function(response){

                                        return response.data;

                                    }, 

                                    function(errResponse){

                                        console.error('Error while fetching users');

                                        return $q.reject(errResponse);

                                    }

                            );

            } ,

            create: function(board){

                return $http.post('http://localhost:8080/board/', board)

                        .then(

                                function(response){

                                 console.log("[service:create]server call  suceeded.");

                                    return response.data;

                                }, 

                                function(errResponse){

                                    console.error('Error while creating article');

                                    return $q.reject(errResponse);

                                }

                        );

            } 

}]);

 

[실행결과]

 

 











4-9-6. 게시판 글읽기

 

  • 간단히 AngularJS 컨트롤러쪽에 함수 하나만 추가하면 된다.

 

[src/main/webapp/js/board_controller.java]

'use strict';


App.controller('BoardController', ['$scope', 'BoardService', 

      function($scope, BoardService) {

          var self = this;

          self.board={id:null, name:'',passwd:'',title:'',content:''};

          self.page=[];

               

          //리스트 보기

          self.list = function(curPage){

              BoardService.list(curPage)

              .then(

                 function(data) {

                     self.page = data;

                     console.log("[controller:list]", self.page);

                     //alert("목록보기 성공!");

                 },

                 function(errResponse){

                     console.error('Error while fetching page...');

                 }

              );

          };   

          

          //글 입력

          self.create = function(board) {

              BoardService.create(board)

              .then(

                  function() {

                   alert("Save OK!");

                   self.list(0);

                  }, 

                  function(errResponse){

                     console.error('Error while creating Article.');

                  } 

               );    

           }; 

 

          self.list(0);

          

          // ADD or UPDATE 버튼 클릭

          self.submit = function() {

              if(self.board.id===null){                      

                  self.create(self.board);          

                  console.log("[controller:create]", self.board);

              }else{

                  //self.update(self.board, self.board.id);

                  console.log('Article updated with id ', self.board.id);

              }

              self.reset();              

          };   

          

          //글읽기

          self.edit = function(id){

              

              for(var i = 0; i < self.page.content.length; i++){

                  if(self.page.content[i].id === id) {

                     self.board = angular.copy(self.page.content[i]);

                     console.log("[read article]", self.board);

                     break;

                  }

              }

          };  

          

          self.reset = function(){

           self.board={id:null, name:'',passwd:'',title:'',content:''};

              $scope.myForm.$setPristine(); //reset Form

          };

          

}]);

 







4-9-7. 게시판 글삭제

 

[src/main/webapp/js/board_controller.java]

'use strict';


App.controller('BoardController', ['$scope', 'BoardService', 

      function($scope, BoardService) {

          var self = this;

          self.board={id:null, name:'',passwd:'',title:'',content:''};

          self.page=[];

               

          //리스트 보기

          self.list = function(curPage){

              BoardService.list(curPage)

              .then(

                 function(data) {

                     self.page = data;

                     console.log("[controller:list]", self.page);

                     //alert("목록보기 성공!");

                 },

                 function(errResponse){

                     console.error('Error while fetching page...');

                 }

              );

          };   

          

          //글 입력

          self.create = function(board) {

              BoardService.create(board)

              .then(

                  function() {

                   alert("Save OK!");

                   self.list(0);

                  }, 

                  function(errResponse){

                     console.error('Error while creating Article.');

                  } 

               );    

           }; 

           

           //글 삭제

           self.delete = function(id){

               BoardService.delete(id)

                       .then(

                               function() {

                               alert("Delete OK!");

                               self.list(self.page.number);  //현재 페이지 리로드

                               }, 

                               function(errResponse){

                                    console.error('Error while deleting Article.');

                               } 

                   );

           };

           

          self.list(0);

          

          // ADD or UPDATE 버튼 클릭

          self.submit = function() {

              if(self.board.id===null){                      

                  self.create(self.board);          

                  console.log("[controller:create]", self.board);

              }else{

                  //self.update(self.board, self.board.id);

                  console.log('Article updated with id ', self.board.id);

              }

              self.reset();              

          };   

          

          //글읽기

          self.edit = function(id){

              console.log('[controller:edit]', id);

              console.log("3333", self.page);

              for(var i = 0; i < self.page.content.length; i++){

                  if(self.page.content[i].id === id) {

                     self.board = angular.copy(self.page.content[i]);

                     console.log("[read article]", self.board);

                     break;

                  }

              }

          };  

          

          //글 삭제

          self.remove = function(id){

           if (confirm('Are you sure you want to delete this article?')) {

           console.log('[controller:remove]', id);

                  //글입력(수정)화면 CLEAR

                  if(self.board.id === id) {  

                     self.reset();

                  }

                  self.delete(id);

         } else {

             return;

         }              

          };

          

          self.reset = function(){

           self.board={id:null, name:'',passwd:'',title:'',content:''};

              $scope.myForm.$setPristine(); //reset Form

          };

          

}]);

 

[src/main/webapp/js/board_service.java]

'use strict';

 

App.factory('BoardService', ['$http', '$q', function($http, $q){

 

    return {

         

            list: function(curPage) {

                    return $http.get('http://localhost:8080/board/' +  curPage)

                            .then(

                                    function(response){

                                     console.log("[service:list]server call  suceeded.");

                                        return response.data;

                                    }, 

                                    function(errResponse){

                                        console.error('Error while fetching contents');

                                        return $q.reject(errResponse);

                                    }

                            );

            } ,

            create: function(board){

                return $http.post('http://localhost:8080/board/', board)

                        .then(

                                function(response){

                                 console.log("[service:create]server call  suceeded.");

                                    return response.data;

                                }, 

                                function(errResponse){

                                    console.error('Error while creating article');

                                    return $q.reject(errResponse);

                                }

                        );

            },

            delete: function(id){

                return $http.delete('http://localhost:8080/board/'+id)

                        .then(

                                function(response){

                                    return response.data;

                                }, 

                                function(errResponse){

                                    console.error('Error while deleting article');

                                    return $q.reject(errResponse);

                                }

                        );

            }

    };

 }]);

 

[BoardController.java 추가]


//---------------------------------------------

// 게시판 글 삭제

//---------------------------------------------

@RequestMapping(value="/delete/{id}", method = RequestMethod.GET)

public ResponseEntity<Void> delete(@PathVariable Integer id) {

boardService.delete(id);

return new ResponseEntity<Void>(HttpStatus.CREATED);

}

 

[BoardService.java 추가]

//글삭제

public void delete(Integer id);

 

[BoardServiceImpl.java]

@Override

//-----------------------------------------

// 글 삭제

//-----------------------------------------

public void delete(Integer id) {

boardRepository.delete(id);

}

 

















4-9-8. 게시판 글수정

 

[board_controller.js]

'use strict';


App.controller('BoardController', ['$scope', 'BoardService', 

      function($scope, BoardService) {

          var self = this;

          self.board={id:null, name:'',passwd:'',title:'',content:''};

          self.page=[];

               

          //리스트 보기

          self.list = function(curPage){

              BoardService.list(curPage)

              .then(

                 function(data) {

                     self.page = data;

                     console.log("[controller:list]", self.page);

                     //alert("목록보기 성공!");

                 },

                 function(errResponse){

                     console.error('Error while fetching page...');

                 }

              );

          };   

          

          //글 입력

          self.create = function(board) {

              BoardService.create(board)

              .then(

                  function() {

                   alert("Save OK!");

                   self.list(0);

                  }, 

                  function(errResponse){

                     console.error('Error while creating Article.');

                  } 

               );    

           }; 

           

           //글 수정

           self.update = function(board, id){

               BoardService.update(board, id)

                       .then(

                       function() {

                                alert("Update OK!");

                                self.list(self.page.number);  //현재 페이지 리로드

                               }, 

                               function(errResponse){

                                    console.error('Error while updating User.');

                               } 

                   );

           };

           

           //글 삭제

           self.delete = function(id){

               BoardService.delete(id)

                       .then(

                               function() {

                               alert("Delete OK!");

                               self.list(self.page.number);  //현재 페이지 리로드

                               }, 

                               function(errResponse){

                                    console.error('Error while deleting Article.');

                               } 

                   );

           };

           

          self.list(0);

          

          // ADD or UPDATE 버튼 클릭

          self.submit = function() {

              if(self.board.id===null){                      

                  self.create(self.board);          

                  console.log("[controller:create]", self.board);

              }else{

                  self.update(self.board, self.board.id);

                  console.log('Article updated with id ', self.board.id);

              }

              self.reset();              

          };   

          

          //글읽기

          self.edit = function(id){

              console.log('[controller:edit]', id);

              console.log("3333", self.page);

              for(var i = 0; i < self.page.content.length; i++){

                  if(self.page.content[i].id === id) {

                     self.board = angular.copy(self.page.content[i]);

                     console.log("[read article]", self.board);

                     break;

                  }

              }

          };  

          

          //글 삭제

          self.remove = function(id){

           if (confirm('Are you sure you want to delete this article?')) {

           console.log('[controller:remove]', id);

                  //글입력(수정)화면 CLEAR

                  if(self.board.id === id) {  

                     self.reset();

                  }

                  self.delete(id);

         } else {

             return;

         }              

          };

          

          self.reset = function(){

           self.board={id:null, name:'',passwd:'',title:'',content:''};

              $scope.myForm.$setPristine(); //reset Form

          };

          

}]);

 

[board_service.js]

'use strict';

 

App.factory('BoardService', ['$http', '$q', function($http, $q){

 

    return {

         

            list: function(curPage) {

                    return $http.get('http://localhost:8080/board/' +  curPage)

                            .then(

                                    function(response){

                                     console.log("[service:list]server call  suceeded.");

                                        return response.data;

                                    }, 

                                    function(errResponse){

                                        console.error('Error while fetching contents');

                                        return $q.reject(errResponse);

                                    }

                            );

            } ,

            create: function(board){

                return $http.post('http://localhost:8080/board/', board)

                        .then(

                                function(response){

                                 console.log("[service:create]server call  suceeded.");

                                    return response.data;

                                }, 

                                function(errResponse){

                                    console.error('Error while creating article');

                                    return $q.reject(errResponse);

                                }

                        );

            },

            delete: function(id){

                return $http.delete('http://localhost:8080/board/'+id)

                        .then(

                                function(response){

                                    return response.data;

                                }, 

                                function(errResponse){

                                    console.error('Error while deleting article');

                                    return $q.reject(errResponse);

                                }

                        );

            },

            update: function(board, id){

                return $http.put('http://localhost:8080/board/'+id, board)

                        .then(

                                function(response){

                                    return response.data;

                                }, 

                                function(errResponse){

                                    console.error('Error while updating board');

                                    return $q.reject(errResponse);

                                }

                        );

            }         

    };

 }]);

 

[BoardService.java 추가]

//글수정

public void update(Board board, Integer id);

 

[BoardServiceImpl.java 추가]


@Override

//-----------------------------------------

// 글 수정

//-----------------------------------------

public void update(Board board, Integer id) {

board.setId(id);

boardRepository.save(board);

}

 

[BoardController.java 추가]


//---------------------------------------------

// 게시판 글 수정

//---------------------------------------------

@RequestMapping(value="/{id}", method = RequestMethod.PUT)

public ResponseEntity<Board> delete(@RequestBody Board board, 

                          @PathVariable Integer id) {

boardService.update(board, id);

return new ResponseEntity<Board>(board, HttpStatus.OK);

}


#스프링부트게시판, #스프링부트, #JPA, #JPA교육, #JPA강좌, #JPA게시판, #스프링게시판, #마이바티스게시판, #JPA게시판,스프링부트게시판, 스프링부트, JPA, JPA교육, JPA강좌, JPA게시판, 스프링게시판, 마이바티스게시판, JPA게시판,

오라클 동의어(Oracle Synonym)? 오라클19C 사용자생성, 권한부여 후 동의어 작성 실습, 오라클학원교육/오라클동영상

 

오라클 동의어(Oracle Synonym)? 오라클19C 사용자생성, 권한부여 후 동의어 작성 실습, 오라클학원교육/오라클동영상


http://ojc.asia/bbs/board.php?bo_table=LecOracle&wr_id=297 


오라클 동의어(Oracle Synonym)? 오라클19C 사용자생성, 권한부여 후 동의어 작성 실습

오라클 동의어(Oracle Synonym)? 오라클19C 사용자생성, 권한부여 후 동의어 작성 실습오라클 동의어(Oracle Synonym)동의어란?오라클19C USER 생성, 권한부여 후 동의어 작성 실습오라클 동의어synonym는 테

ojc.asia

오라클 동의어(Oracle Synonym)





https://youtu.be/Fz3r6jNhXUs

https://youtu.be/opiGhCDZDBY


동의어란?

오라클19C USER 생성, 권한부여 후 동의어  작성 실습





오라클 동의어synonym는 테이블, 뷰, 시퀀스, 프로그램 유닛(함수, 프로시저,  패키지)에 대한 별명이며 공용(public), 전용(private) 두가지 형태로 작성 가능 합니다. 


모든 계정에서 접근 가능한 공용 동의어public synonym는 DBA 권한을 가진 사용자만이 생성 가능하고, 전용 동의어private synonym는 동의어로 작성 될 원본객체에 대한 접근 권한을 얻은 사용자가 작성하는 동의어로 해당 USER에서만 사용 가능 합니다.


동의어는 단순한 별칭 이므로 데이터 딕셔너리data dictionary에서 정의 외 다른 저장 공간이 필요하지는 않습니다. 


동의어는 보안과 편의성 때문에 사용되는데 객체의 이름 및 소유자를 가릴 수 있습니다. 또 분산 환경에서 원격 객체에 대한 위치 투명성 제공합니다. 동의어로 만들어진 테이블의  이름을 바꾸거나 이동해야하는 경우 동의어 만 다시 정의하면되기 때문에 이 방법이 유용하며 동의어를 기반으로하는 응용 프로그램은 수정없이 계속 사용 가능 합니다.


동의어는 스키마 오브젝트를 직접 참조 합니다. 예를 들어 SCOTT 계정에서 EDU라는 계정의 CUSTOMER 테이블을 참조할 때 EDU.CUSTOMER 라고 써주어야 하는데 여러 번 사용되는 경우에는 이름이 길어서 불편 합니다. 이러한 경우 EDU.CUSTOMER 에 대한 동의어(예를들면 , EC)를 만들어서 사용하면 편리 합니다.


SELECT * FROM EC;


[기본형식]

CREATE [PUBLIC] SYNONYM [schema.] synonym_name
FOR [schema.]object;

  • PUBLIC : 공용 동의어를 정의하며 생략하면 전용 동의어를 정의합니다.


실제 EDU 사용자를 생성하고 테이블을 만들어서 SCOTT 계정에서 동의어를 만들고 이를 딕셔너리 뷰에서 확인 후 삭제해 보겠습니다. 


실습


실습을 위한 EDU 사용자 계정을 생성합니다. 오라클12C 이후 사용자 생성시 앞에 C##을 붙여야만 하는데, 오라클12C 이전 방식과 동일한 방식으로 사용자를 생성하기 위해 세션 레벨에서 “_ORACLE_SCRIPT”=TRUE라고 설정을 해야 합니다.


현재 세션에서 오라클 12C 이전 스크립트방식을 지원하면서 사용자를 생성하기 위해 _ORACLE_SCRIPT를 TRUE로 설정하세요.


ALTER SESSION SET "_ORACLE_SCRIPT"=TRUE; 


<실행결과>

Session이(가) 변경되었습니다.


새로운 사용자 계정을 생성 합니다.(SCOTT 계정은 DBA 권한을 부여 받았으므로 CREATE USER가 가능 합니다.)


ID : EDU, PASSWORD : EDU으로 사용자 계정을 생성하세요.


CREATE USER EDU IDENTIFIED BY EDU;


<실행결과>

User EDU이(가) 생성되었습니다.


오라클에 접속을 하기위한 롤role과 테이블 등을 생성할 수 있는 롤을 부여합니다. 롤은 권한privilege을 여러개 합쳐놓은 것 입니다.


생성한 사용자 계정에 CONNECT, RESOURCE 롤을 부여하세요.


GRANT CONNECT, RESOURCE TO EDU;


<실행결과>

Grant을(를) 성공했습니다.


CONNECT 롤에는 ALTER SESSION, CREATE SESSION 권한이 포함되어 있고, RESOURCE 롤에는 CREATE CLUSTER, CREATE INDEXTYPE, CREATE OPERATOR, CREATE PROCEDURE, CREATE SEQUENCE

CREATE TABLE, CREATE TRIGGER, CREATE TYPE 권한이 포함되어 있습니다.


오라클11g 까지는 RESOURCE 롤에 UNLIMITED TABLESPACE 권한이 있어  RESOURCE 롤을 부여후 CREATE TABLE 후 테이블에 INSERT 사용이 가능했지만 12C 이후에는 별도로 부여해야 합니다.(아래 권한이 없으면 테이블이 생성은 되지만 데이터 입력이 불가합니다. )


생성한 사용자 계정에 UNLIMITED TABLESPACE 권한을 부여하세요.


GRANT UNLIMITED TABLESPACE TO EDU;


<실행결과>

Grant을(를) 성공했습니다.


EDU 계정으로 명령프롬프트를 이용하여 오라클 서버에 접속 후 테이블을 생성하고 데이터 2건을 입력 합니다.


생성한 사용자 계정에서 테이블 및 데이터를 생성 하세요.



C:\Users\jclee>sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on 토 12월 4 16:02:53 2021
Version 19.3.0.0.0

Copyright (c) 1982, 2019, Oracle.  All rights reserved.


다음에 접속됨:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

SQL> conn edu/EDU   --비밀번호는 대소문자 구분 합니다.
연결되었습니다.
SQL> create table customer (
  2  id number,
  3  name varchar2(20)
  4  );

테이블이 생성되었습니다.

SQL> insert into customer (id, name) values (1, '1길동');

1 개의 행이 만들어졌습니다.

SQL> insert into customer (id, name) values (2, '2길동');

1 개의 행이 만들어졌습니다.

SQL> commit;

커밋이 완료되었습니다.






SQL Developer의 SCOTT 계정에서 EDU 계정의 CUSTOMER 테이블을 SELECT 합니다. SCOTT 계정은 DBA 롤을 부여받은 계정이므로 SELECT 되지만 일반 다른 사용자에서는 CUSTOMER 테이블에 대한 SELECT 권한을 부여 받아야 SELECT 합니다.


SCOTT 계정에서 EDU 계정의 CUSTOMER 테이블을 SELECT 하세요.


SELECT * FROM EDU.CUSTOMER;


<실행결과>

 
ID
NAME
1
1
1길동
2
2
2길동


EDU.CUSTOMER에 대한 공용 동의어를 생성합니다. 공용 동의어는 모든 사용자 계정에서 접근 가능 합니다.


EDU.CUSTOMER에 대한 동의어  EC를 생성 합니다.


CREATE PUBLIC SYNONYM EC FOR EDU.CUSTOMER;


<실행결과>

SYNONYM EC이(가) 생성되었습니다.


동의어를 통해 데이터를 조회 합니다.


동의어  EC를 SELECT 합니다.


SELECT * FROM EC;


<실행결과>

 
ID
NAME
1
1
1길동
2
2
2길동


생성한 동의어를 딕셔너리 뷰에서 조회 합니다.


동의어  EC를 딕셔너리 뷰에서 조회 합니다.


SELECT OWNER, SYNONYM_NAME, TABLE_OWNER 

FROM    DBA_SYNONYMS

WHERE SYNONYM_NAME = 'EC'  ;


<실행결과>

 
OWNER
SYNONYM_NAME
TABLE_OWNER
1
PUBLIC
RC
RABBIT


​#동의어, #오라클동의어, #SQL동의어, #synonym, #오라클학원, #SQL학원, #SQL교육, #오라클교육, #ORACLE교육, #ORACLE학원, #ORACLE동영상, #ORACLE강좌, #오라클학원동영상, #SQL학원동영상,동의어, 오라클동의어, SQL동의어, synonym, 오라클학원, SQL학원, SQL교육, 오라클교육, ORACLE교육, ORACLE학원, ORACLE동영상, ORACLE강좌, 오라클학원동영상, SQL학원동영상
 

2021년 12월 3일 금요일

[ORACLE교육동영상/오라클학원교육]오라클19C 사용자생성, 권한 및 롤부여, 테이블생성(create table), 오라클학원교육동영상/오라클교육동영상 따라해보세요~

 

[ORACLE교육동영상/오라클학원교육]오라클19C 사용자생성, 권한 및 롤부여, 테이블생성(create table), 오라클학원교육동영상/오라클교육동영상 따라해보세요~


ORACLE 19C

오라클 사용자 생성(CREATE USER)


사용자 생성

권한부여

테이블 및 데이터 입력 실습




http://ojc.asia/bbs/board.php?bo_table=LecOracle&wr_id=296

이미지 썸네일 삭제
오라클19C 사용자생성, 권한 및 롤부여, 테이블생성(create table)

오라클19C 사용자생성, 권한 및 롤부여, 테이블생성(create table)ORACLE 19C오라클 사용자 생성(CREATE USER)사용자 생성권한부여테이블 및 데이터 입력 실습실습“EDU” 라는 이름의 사용자 계정을 생성합니다. 오라클12C 이후 사용자 생성시 앞에 C##을 붙여야만 하는데, 오라클12C 이전 방식과 동일한 방식으로 사용자를 생성하기 …

ojc.asia



실습


“EDU” 라는 이름의 사용자 계정을 생성합니다. 오라클12C 이후 사용자 생성시 앞에 C##을 붙여야만 하는데, 오라클12C 이전 방식과 동일한 방식으로 사용자를 생성하기 위해 세션 레벨에서 “_ORACLE_SCRIPT”=TRUE라고 설정을 해야 합니다.


  • 0열 선택0열 다음에 열 추가
  • 0행 선택0행 다음에 행 추가
셀 전체 선택
열 너비 조절
행 높이 조절
현재 세션에서 오라클 12C 이전 스크립트방식을 지원하면서 사용자를 생성하기 위해 _ORACLE_SCRIPT를 TRUE로 설정하세요.
  • 셀 병합
  • 행 분할
  • 열 분할
  • 너비 맞춤
  • 삭제


ALTER SESSION SET "_ORACLE_SCRIPT"=TRUE;


<실행결과>

Session이(가) 변경되었습니다.


새로운 사용자 계정을 생성 합니다.(SCOTT 계정은 DBA 권한을 부여 받았으므로 CREATE USER가 가능 합니다.)


  • 0열 선택0열 다음에 열 추가
  • 0행 선택0행 다음에 행 추가
셀 전체 선택
열 너비 조절
행 높이 조절
ID : EDU, PASSWORD : EDU으로 사용자 계정을 생성하세요.
  • 셀 병합
  • 행 분할
  • 열 분할
  • 너비 맞춤
  • 삭제


CREATE USER EDU IDENTIFIED BY EDU;


<실행결과>

User EDU이(가) 생성되었습니다.


오라클에 접속을 하기위한 롤role과 테이블 등을 생성할 수 있는 롤을 부여합니다. 롤은 권한privilege을 여러개 합쳐놓은 것 입니다.


  • 0열 선택0열 다음에 열 추가
  • 0행 선택0행 다음에 행 추가
셀 전체 선택
열 너비 조절
행 높이 조절
생성한 사용자 계정에 CONNECT, RESOURCE 롤을 부여하세요.
  • 셀 병합
  • 행 분할
  • 열 분할
  • 너비 맞춤
  • 삭제


GRANT CONNECT, RESOURCE TO EDU;


<실행결과>

Grant을(를) 성공했습니다.


CONNECT 롤에는 ALTER SESSION, CREATE SESSION권한이 포함되어 있고, RESOURCE 롤에는 CREATE CLUSTER, CREATE INDEXTYPE, CREATE OPERATOR, CREATE PROCEDURE, CREATE SEQUENCE

CREATE TABLE, CREATE TRIGGER, CREATE TYPE 권한이 포함되어 있습니다.


오라클11g 까지는 RESOURCE 롤에 UNLIMITED TABLESPACE 권한이 있어 RESOURCE 롤을 부여후 CREATE TABLE 후 테이블에 INSERT 사용이 가능했지만 12C 이후에는 별도로 부여해야 합니다.(아래 권한이 없으면 테이블이 생성은 되지만 데이터 입력이 불가합니다. )


  • 0열 선택0열 다음에 열 추가
  • 0행 선택0행 다음에 행 추가
셀 전체 선택
열 너비 조절
행 높이 조절
생성한 사용자 계정에 UNLIMITED TABLESPACE 권한을 부여하세요.
  • 셀 병합
  • 행 분할
  • 열 분할
  • 너비 맞춤
  • 삭제


GRANT UNLIMITED TABLESPACE TO EDU;


<실행결과>

Grant을(를) 성공했습니다.


EDU 계정으로 명령프롬프트를 이용하여 오라클 서버에 접속 후 테이블을 생성하고 데이터 2건을 입력 합니다.


  • 0열 선택0열 다음에 열 추가
  • 0행 선택0행 다음에 행 추가
셀 전체 선택
열 너비 조절
행 높이 조절
생성한 사용자 계정에서 테이블 및 데이터를 생성 하세요.
  • 셀 병합
  • 행 분할
  • 열 분할
  • 너비 맞춤
  • 삭제



  • 0열 선택0열 다음에 열 추가
  • 0행 선택0행 다음에 행 추가
셀 전체 선택
열 너비 조절
행 높이 조절
C:\Users\jclee>sqlplus / as sysdba


SQL*Plus: Release 19.0.0.0.0 - Production on 토 12월 4 16:02:53 2021
Version 19.3.0.0.0


Copyright (c) 1982, 2019, Oracle. All rights reserved.




다음에 접속됨:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0


SQL> conn edu/EDU --비밀번호는 대소문자 구분 합니다.
연결되었습니다.
SQL> create table customer (
2 id number,
3 name varchar2(20)
4 );


테이블이 생성되었습니다.


SQL> insert into customer (id, name) values (1, '1길동');


1 개의 행이 만들어졌습니다.


SQL> insert into customer (id, name) values (2, '2길동');


1 개의 행이 만들어졌습니다.


SQL> commit;


커밋이 완료되었습니다.


  • 셀 병합
  • 행 분할
  • 열 분할
  • 너비 맞춤
  • 삭제











#오라클USER, #오라클사용자, #CREATEUSER, #ORACLE뷰, #오라클VIEW, #오라클교육, #오라클학원, #ORACLE, #ORACLE교육, #ORACLE학원, #VIEW, #뷰란, #오라클동영상, #ORACLE동영상, #오라클강의, #ORACLE강의, #ORACLE강좌, #오라클강좌, 오라클USER, 오라클사용자, CREATEUSER, 오라클뷰, ORACLE뷰, 오라클VIEW, 오라클교육, 오라클학원, ORACLE, ORACLE교육, ORACLE학원, VIEW, 뷰란, 오라클동영상, ORACLE동영상, 오라클강의, ORACLE강의, ORACLE강좌, 오라클강좌



(C#교육동영상)C# ADO.NET 실습 ODP.NET/ODAC 설치 오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원

  (C#교육동영상)C# ADO.NET 실습  ODP.NET/ODAC 설치  오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원 https://www.youtube.com/watch?v=qIPU85yAlzc&list=PLxU-i...