1. 문제상황

   : Linux 서버 console 환경에서 직접 프로그램소스를 수정하려면 vi 또는 vim 에디터를 통해 주로 수정하게 된다.

     아무래도 편의성이 떨어지기 때문에 익숙하지 않은 사람들은 불편할 수 있다.

     이럴때 Windows 에 설치된 eclipse에서 바로 수정할 수 있으면 하는 생각들을 했을 것이다.

     eclipse plugin 프로그램인 Remote System Explorer를 추가하면 문제를 해결할 수 있다.


2. 설치방법

   1) plugin 설치

     : Help > Eclipse Marketplace 에서 "remote"단어로 검색하면 아래에 Remote System Explorer가 나온다.==> install

   2) 오른쪽 상단의 Open Perspective 아이콘을 클릭하고 Remote System Explorer를 선택한다.


   3) 왼쪽 상단의 일반적인 연결 아이콘을 클릭한 후 SSH Only를 선택한 후 Next를 누른다. (요즘은 주로 SFTP이므로)

   4) 본인의 경우 Virtual Box에 CentOS를 설치했기에 Localhost Host Name을 셋팅했음.

       외부서버에 설치했으면 아이피를 host name자리에 입력하면 되겠다.



      - 위에서 Next 클릭한 화면


    - 위에서 Finish 클릭한 화면


   5) 이제 Sftp Files 하위를 열려고 시도하면 접속 ID, Password입력하라는 팝업이 뜬다.

      - 제대로 입력하면 아래와 같이 나오는데 파일을 찾아 바로 수정하고 저장하면 된다.



어때요? 도움이 많이 되셨나요? ~~~~~~~



1. 무료쇼핑몰 QOR 

  - QOR은 비즈니스 애플리케이션, CMS 및 전자 상거래 시스템에 필요한 공통 기능을 추상화 한 Go로 작성된 라이브러리

   세트입니다. 원래 QOR은 Ruby on Rails로 만들어졌으나 Go언어로 재작성 된 CMS 쇼핑몰 오픈소스입니다.

  - example 사이트 : https://github.com/qor/qor-example

  

2. 설치순서

  - 사이트에 나와있는 설치순서대로 하면 되지만 정상적으로 돌아가게 하기 위해

    몇가지 추가적인 수정이 필요하여 그 경험을 공유합니다.

# go get으로 github에서 소스를 받는다. (git 설치 안되어있으면 yum install git 으로)

#아래 명령어를 실행하면 앞 게시물(https://dodo-it.tistory.com/65)에서 go 설치시 지정한 go_work 하위에 다운로드됨. 

$ go get -u github.com/qor/qor-example


# mariadb를 설치(https://dodo-it.tistory.com/7)하고 아래와 같이 접속(root계정으로)하여 

# qor_example 데이터베이스를 만든다. (mariadb 설치시 root의 접속비밀번호는 1로 설정함)

$ mysql -uroot -p

mysql> CREATE DATABASE qor_example;


# DB 설정 및 프로그램 수정

#1) DB 연결설정

#2) 프로그램수정 (원본예제대로 하면 로긴안되고 제품리스트에서 제품 클릭하면 상세페이지로 넘어가지 않는다.)

#==> 아래에 추가적으로 설명한것을 참고로 수정한다.


#샘플데이터를 DB에 생성한다.

#생성시 SSL오류가 발생하면 /etc/yum.conf 을 vi에디터로 열고 sslverify=false 로 설정한다.

$ go run config/db/seeds/main.go config/db/seeds/seeds.go


# qor-example 경로로 이동 후 서버를 구동시켜본다.

# 참고로 윈도우에서 경로이동시에는 cd %GOPATH%/src/github.com/qor/qor-example 를 사용한다.

$ cd $GOPATH/src/github.com/qor/qor-example

$ go run main.go



3. DB 설정 및 프로그램 수정

  1) DB설정

    - /usr/local/go_work/src/github.com/qor/qor-example/config 하위에 보면 샘플설정파일이 몇개 있다.

     그중에 샘플데이터 생성을 위해 database.example.yml 파일을 database.yml 로 복사 후 내부에 패스워드를 설정한다.

#경로이동

$ cd $GOPATH/src/github.com/qor/qor-example/config


#파일 복사 후 rename

$ mv database.example.yml database.yml

 

#database.yml 파일 수정 ==> password: 1 을 아래에 추가함.(패스워드는 mariadb root 패스워드 설정시 1로 설정함)

$ vi database.yml 

------------------------------------------------------------

db:

  adapter: mysql

  name: qor_example

  user: root

  password: 1          

-----------------------------------------------------------

# 저장 후 빠져나오기 ==> esc클릭-> ':' 입력 후 --> wq 입력



  2) 프로그램수정

    a) 로긴안되는 문제 수정

      ==> /usr/local/go_work/src/github.com/qor/auth/providers/password/handlers.go 파일 수정

package password


import (

"reflect"

"strings"


"github.com/qor/auth"

"github.com/qor/auth/auth_identity"

"github.com/qor/auth/claims"

"github.com/qor/qor/utils"

"github.com/qor/session"

)


// DefaultAuthorizeHandler default authorize handler

var DefaultAuthorizeHandler = func(context *auth.Context) (*claims.Claims, error) {

var (

                //authInfo    auth_identity.Basic <== 기존소스 Basic을 AuthIdentity 로 수정             

authInfo    auth_identity.AuthIdentity               

req         = context.Request

tx          = context.Auth.GetDB(req)

provider, _ = context.Provider.(*Provider)

)


req.ParseForm()

authInfo.Provider = provider.GetName()

authInfo.UID = strings.TrimSpace(req.Form.Get("login"))


if tx.Model(context.Auth.AuthIdentityModel).Where(authInfo).Scan(&authInfo).RecordNotFound() {

return nil, auth.ErrInvalidAccount

}


if provider.Config.Confirmable && authInfo.ConfirmedAt == nil {

currentUser, _ := context.Auth.UserStorer.Get(authInfo.ToClaims(), context)

provider.Config.ConfirmMailer(authInfo.UID, context, authInfo.ToClaims(), currentUser)


return nil, ErrUnconfirmed

}


if err := provider.Encryptor.Compare(authInfo.EncryptedPassword, strings.TrimSpace(req.Form.Get("password"))); err == nil {

return authInfo.ToClaims(), err

}


return nil, auth.ErrInvalidPassword

}


// DefaultRegisterHandler default register handler

var DefaultRegisterHandler = func(context *auth.Context) (*claims.Claims, error) {

var (

err         error

currentUser interface{}

schema      auth.Schema

//authInfo    auth_identity.Basic <== 기존소스 Basic을 AuthIdentity 로 수정             

authInfo    auth_identity.AuthIdentity       

req         = context.Request

tx          = context.Auth.GetDB(req)

provider, _ = context.Provider.(*Provider)

)


req.ParseForm()

if req.Form.Get("login") == "" {

return nil, auth.ErrInvalidAccount

}


if req.Form.Get("password") == "" {

return nil, auth.ErrInvalidPassword

}


authInfo.Provider = provider.GetName()

authInfo.UID = strings.TrimSpace(req.Form.Get("login"))


if !tx.Model(context.Auth.AuthIdentityModel).Where(authInfo).Scan(&authInfo).RecordNotFound() {

return nil, auth.ErrInvalidAccount

}


if authInfo.EncryptedPassword, err = provider.Encryptor.Digest(strings.TrimSpace(req.Form.Get("password"))); err == nil {

schema.Provider = authInfo.Provider

schema.UID = authInfo.UID

schema.Email = authInfo.UID

schema.RawInfo = req


currentUser, authInfo.UserID, err = context.Auth.UserStorer.Save(&schema, context)

if err != nil {

return nil, err

}


// create auth identity

authIdentity := reflect.New(utils.ModelType(context.Auth.Config.AuthIdentityModel)).Interface()

if err = tx.Where(authInfo).FirstOrCreate(authIdentity).Error; err == nil {

if provider.Config.Confirmable {

context.SessionStorer.Flash(context.Writer, req, session.Message{Message: ConfirmFlashMessage, Type: "success"})

err = provider.Config.ConfirmMailer(schema.Email, context, authInfo.ToClaims(), currentUser)

}


return authInfo.ToClaims(), err

}

}


return nil, err

}



   b) 제품리스트에서 제품 클릭하면 상세페이지로 넘어가지 않는 문제 수정

      ==> /usr/local/go_work/src/github.com/qor/qor-example/app/products/views/gender.tmpl 수정

<main class="container product_index">


<div class="grid">

  <div class="grid__col is-2 product_options">

    <h2>CATEGORIES</h2>

    <ul>

      {{ range $category := get_categories }}

        <li><a href="{{ $category.DefaultPath }}">{{$category.Name}}</a></li>

      {{ end }}

    </ul>


    <h2>COLORS</h2>

    <ul class="product_options-color">

      <li><a rel="nofollow" href="#"><span style="background:#eae3d3"></span>Beige</a></li>

      <li><a rel="nofollow" href="#"><span style="background:#222"></span>Black</a></li>

      <li><a rel="nofollow" href="#"><span style="background:#f79858"></span>Blue</a></li>

      <li><a rel="nofollow" href="#"><span style="background:#f56060"></span>Brown</a></li>

      <li><a rel="nofollow" href="#"><span style="background:#44c28d"></span>Green</a></li>

      <li><a rel="nofollow" href=""><span style="background:#999"></span>Grey</a></li>

      <li><a rel="nofollow" href=""><span style="background:#f79858"></span>Orange</a></li>

      <li><a rel="nofollow" href=""><span style="background:#b27ef8"></span>Purple</a></li>

      <li><a rel="nofollow" href=""><span style="background:#f56060"></span>Red</a></li>

      <li><a rel="nofollow" href=""><span style="background:#fff;border: 1px solid #e8e9eb;width:13px;height:13px;"></span>White</a></li>

    </ul>


    <h2>SIZES</h2>

    <ul class="product_options-size">

      <li><a rel="nofollow" href="#">XS</a></li>

      <li><a rel="nofollow" href="#">S</a></li>

      <li><a rel="nofollow" href="#">M</a></li>

      <li><a rel="nofollow" href="#">L</a></li>

      <li><a rel="nofollow" href="#">XL</a></li>

      <li><a rel="nofollow" href="#">XXL</a></li>

    </ul>

  </div>


  <div class="grid__col is-10 product_lists">

    <h1>ALL PRODUCTS (8)</h1>

    <ul class="grid">

      {{range .Products}}

        <li class="grid__col is-3">

          <!--<a href="{{.DefaultPath}}"> ==> 이미지클릭시 상세링크 부분으로 계속 초기페이지로 간다.  -->

          <a href="{{.DefaultPath}}products/{{.Code}}"> <!-- ==> 정확한 상세페이지 URL이 되도록 수정한다. -->

            <div class="product_image" style="background-image: url({{.MainImageURL}});">

              <div class="image_overlay"></div>

              <div class="add_to_cart">Add to cart</div>

              <div class="stats">

                <div class="stats-container">

                  <span class="product_price">${{.Price}}</span>

                  <span class="product_name">{{.Name}}</span>


                  <div class="product_meta">

                    <strong>SIZES</strong>

                    <span>

                      XS, S, M, L, XL, XXL

                    </span>

                    <strong>COLORS</strong>

                    <div class="colors">

                      <span style="background:#f79858"></span>

                      <span style="background:#f56060"></span>

                      <span style="background:#44c28d"></span>

                      <span style="background:#f79858"></span>

                    </div>

                  </div>

                </div>

              </div>

            </div>

          </a>

        </li>

      {{end}}

    </ul>

  </div>

</div>

</main>

 


4. 실행화면

  1) 사용자 접속 URL : http://localhost:7000






  2) 관리자 접속 URL : http://localhost:7000/admin




어때요? 도움이 많이 되셨나요? ~~~~~~~


'Programming Languages > Golang(Go)' 카테고리의 다른 글

CentOS7 Golang(Go언어) 설치  (0) 2018.12.03

1. 상황

  : 알리익스프레스에서 물품을 주문했으나, 배송상태가 잘 진행되다가 갑자기 "지역 법률에 의해 통관에서 걸림"이라는

    황당한 상태가 나올 경우가 있음.

    당연히 주문한 물품은 저렴하고 법에 저촉을 받지 않는 순수한 제품이었지요. 

  


2. 우체국 EMS 검색해보기

   1) 바로 위 이미지에 "추적번호" 빨간색으로 테두리 친 부분을 복사한다.

   2) 우체국 EMS사이트로 접속 후 오른쪽 하단의 "EMS행방조회"에서 추적번호를 입력한 뒤 조회한다.

      URL : https://ems.epost.go.kr/comm.RetrievePostagEMSSrvcCenter.postal

   


   3) 조회결과 확인

     : 조회하면 위 알리익스프레스 사이트에서 통관에 걸렸다는 물품이 국내 우체국으로 들어와 

       열심히 우리집으로 달려오고 있는것을 알 수 있다..^^



어때요? 도움이 많이 되셨나요? ~~~~~~~


1. Linux에 Golang 설치방법

  1) 본인은 usr/local 하위에 설치할 것입니다.

     - 로긴 후 이동 : cd /usr/local


  2) Go 파일 다운로드

    - Go 사이트(https://golang.org/dl/)의 파일 다운로드페이지에서 linux 용 go 파일의 link를 복사한다.

   


   - 앞에서 이동한 Linux의 /usr/local 에 파일 다운로드(wget 이용, wget이 미설치인 경우 --> yum install wget )   

 

    wget https://dl.google.com/go/go1.11.2.linux-amd64.tar.gz --no-check-certificate



  3) 받은파일 압축해제 (그러면 go 폴더가 생긴다)

    tar -C /usr/local -xzf go1.11.2.linux-amd64.tar.gz


  4) 실행파일 path설정 (명력어 수행위치는 아무데서나 실행해도 됨)

    - 실행파일 path 환경등록

     export PATH=$PATH:/usr/local/go/bin

     

   - path적용(명력어 수행위치는 아무데서나 실행해도 됨)

     source ~/.bash_profile


  5) GOROOT 지정 (선택사항, 궂이 안해되 될 듯)
   : Go가 설치된 곳의 위치를 환경에 설정한다.
   - 환경에 GOROOT추가

    export GOROOT=/usr/local/go 

   - 환경적용

    source ~/.bash_profile

      

  6) GOPATH 지정 (필수, go get -u 패키지주소 로 패키지 설치시 GOPATH에 설치됨)

    : Go 는 실제 프로그램을 할 곳인 GOPATH를 지정해야 함.(여기서는 /usr/local/go-work 를 지정할것임.)

   - 일단 go-work폴더를 /usr/local하위에 만든다.

    mkdir /usr/local/go_work 

   - 환경에 GOPATH 추가  

    export GOPATH=/usr/local/go_work

   - 환경적용

    source ~/.bash_profile

  

  7) go 설치 확인해보기 (go 명령어로 version이 잘 나오면 설치가 잘 된 것임.)

     go version 



어때요? 도움이 많이 되셨나요? ~~~~~~~


3. 실제 구현

   : 이번시간에는 앞에서 설명한 대로 실제 중복체크기능을 어떻게 구현할지 소스를 보면서 설명하도록 하겠습니다.


  1) javascript(product.js)에서 로직 추가

var fnObj = {};

var ACTIONS = axboot.actionExtend(fnObj, {

    PAGE_SEARCH: function (caller, act, data) {   

        axboot.ajax({

            type: "GET",

            url: ["product"],

            data: caller.searchView.getData(),

            callback: function (res) {

            //중복기능추가용: 조회할때 기존 조회건인지를 확인하기 위해 __searched__ 속성을 더 붙여준다.

            for ( var i = 0; i < res.list.length; i++) {

            res.list[i].__searched__= true;

                }

                caller.gridView01.setData(res);

            }

        });

        return false;

    },

    PAGE_SAVE: function (caller, act, data) {

        var saveList = [].concat(caller.gridView01.getData("modified"));

        saveList = saveList.concat(caller.gridView01.getData("deleted"));  


        axboot.ajax({

            type: "PUT",

            url: ["product"],

            data: JSON.stringify(saveList),

            callback: function (res) {

                ACTIONS.dispatch(ACTIONS.PAGE_SEARCH);

                axToast.push(LANG("onsave"));

            },

            options: {

                    onError: function(err){

                    //{"message":"신규로 추가하신 [제품코드]코드는 이미 등록된 제품코드입니다."}

                       axDialog.alert({

                        title: "Error",

                            theme: "primary",

                            width:450,

                            msg: err.message

                        });    

                 }

        }

        });

    },

    ITEM_ADD: function (caller, act, data) {

        caller.gridView01.addRow();

    },

    ITEM_DEL: function (caller, act, data) {   

        caller.gridView01.delRow("selected");    

    }

});


var CODE = {};  //추가

// fnObj 기본 함수 스타트와 리사이즈

fnObj.pageStart = function () {

//

var _this = this;  


    axboot

        .call({

            type: "GET", url: "/api/v1/commonCodes", data: {groupCd: "ORIGIN"},

            callback: function (res) {

                var originList = [];

                res.list.forEach(function (n) {

                originList.push({

                CD: n.code, NM: n.name + "(" + n.code + ")"                        

                    });

                });

                this.originList = originList;

            }

        })        

        .done(function () {

            CODE = this; // this는 call을 통해 수집된 데이터들.

//위쪽 추가

            _this.pageButtonView.initView();  // this --> _this 로 변경

            _this.searchView.initView();  // this --> _this 로 변경

            _this.gridView01.initView();  // this --> _this 로 변경

    ACTIONS.dispatch(ACTIONS.PAGE_SEARCH);

        });  //추가

};


fnObj.pageResize = function () {


};



fnObj.pageButtonView = axboot.viewExtend({

    initView: function () {

        axboot.buttonClick(this, "data-page-btn", {

            "search": function () {

                ACTIONS.dispatch(ACTIONS.PAGE_SEARCH);

            },

            "save": function () {

                ACTIONS.dispatch(ACTIONS.PAGE_SAVE);

            }

        });

    }

});


//== view 시작

/**

 * searchView

 */

fnObj.searchView = axboot.viewExtend(axboot.searchView, {

    initView: function () {

        this.target = $(document["searchView0"]);

        this.target.attr("onsubmit", "return ACTIONS.dispatch(ACTIONS.PAGE_SEARCH);");

        this.filter = $("#filter");

    },

    getData: function () {

        return {

            pageNumber: this.pageNumber,

            pageSize: this.pageSize,

            filter: this.filter.val()

        }

    }

});



/**

 * gridView

 */

var list = [];

fnObj.gridView01 = axboot.viewExtend(axboot.gridView, {

    initView: function () {

        var _this = this;

        this.originList = CODE.originList; //추가

        

        this.target = axboot.gridBuilder({

            showRowSelector: true,

            frozenColumnIndex: 0,

            sortable: true,

            multipleSelect: true,

            target: $('[data-ax5grid="grid-view-01"]'), 

            columns: [

            {key: "prdtCd", label: "제품코드", width: 100, align: "center", editor: "text"},

                {key: "prdtNm", label: "제품명", width: 200, align: "center", editor: "text"},

                {

                    key: "origin", label: "원산지", width: 100,align: "center", editor: {

                    type: "select", config: {

                        columnKeys: {

                            optionValue: "CD", optionText: "NM"

                        },

                        options: this.originList //추가

                        /*

                        [

                        {"CD":"KR","NM":"한국(KR)"},

                        {"CD":"US","NM":"미국(US)"},

                        {"CD":"JP","NM":"일본(JP)"}

                        ]

                        */

                        

                    }

                  }

                },

                {key: "purchasePrice", label: "매입가격", width: 150, align: "right", editor: "number"},

                {key: "salesPrice", label: "판매가격", width: 150, align: "right", editor: "number"}          

            ],

            body: {

                onClick: function () {

                    this.self.select(this.dindex, {selectedClear: true});

                }

            }

        });


        axboot.buttonClick(this, "data-grid-view-01-btn", {

            "add": function () {

                ACTIONS.dispatch(ACTIONS.ITEM_ADD);

            },

            "delete": function () {

                ACTIONS.dispatch(ACTIONS.ITEM_DEL);

            }

        });

    },

    getData: function (_type) {   

        var _list = this.target.getList(_type);

        

        if (_type == "modified" || _type == "deleted") {

            list = ax5.util.filter(_list, function () {

                return this.prdtCd ;

            });

        } else {

            list = _list;

        }                

        

        return list;

    },

    addRow: function () {   

        this.target.addRow({__created__: true, origin: "KR"}, "last");

    },

    delRow: function delRow(_type) {    


    this.target.deleteRow(_type);  //여기서 무조건 deleteList에 추가해주고 있는것 같다.

   

    //그렇다보니 기존 조회된 데이터가 아닌 신규로 추가한 후 삭제해도 추가되기 때문에 

    //저장시 안넘어가도 되는 데이터(화면상에서만 행추가후 삭제시)까지 날라간다.

        

        //중복기능추가시: 조회된것이 아닌경우 deleteList에서 빼준다.        

        for(i=0;i<this.target.deletedList.length ;i++)

        {

        if(this.target.deletedList[i].__searched__==undefined)

        {

        this.target.deletedList[i]=null;

        }

        }

        

    }

});


2) Controller(ProductController) 에서 로직 추가

package com.dasdes.shopmng.controllers;


import com.chequer.axboot.core.api.response.Responses;

import com.chequer.axboot.core.controllers.BaseController;

import com.chequer.axboot.core.parameter.RequestParams;

import org.springframework.stereotype.Controller;


import com.chequer.axboot.core.api.ApiException;

import com.chequer.axboot.core.api.response.ApiResponse;

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

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

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

import com.dasdes.shopmng.domain.prdt.Product;

import com.dasdes.shopmng.domain.prdt.ProductService;

import com.wordnik.swagger.annotations.ApiImplicitParam;  

import com.wordnik.swagger.annotations.ApiImplicitParams; 


import javax.inject.Inject;

import java.util.List;


@Controller

@RequestMapping(value = "/api/v1/product")

public class ProductController extends BaseController {


    @Inject

    private ProductService productService;


    @RequestMapping(method = RequestMethod.GET, produces = APPLICATION_JSON)

    @ApiImplicitParams({

            @ApiImplicitParam(name = "prdtCd", value = "제품코드", dataType = "String", paramType = "query"),

            @ApiImplicitParam(name = "prdtNm", value = "제품명", dataType = "String", paramType = "query"),

            @ApiImplicitParam(name = "filter", value = "검색어", dataType = "String", paramType = "query")

    })    

    public Responses.ListResponse list(RequestParams<Product> requestParams) {

        List<Product> list = productService.gets(requestParams);

        return Responses.ListResponse.of(list);

    }


    @RequestMapping(method = {RequestMethod.PUT}, produces = APPLICATION_JSON)

    public ApiResponse save(@RequestBody List<Product> request) {

   

    //중복체크 후 중복발생 시 Exception핸들러로 받는다.

    try

    {

           productService.savePrdt(request);

    }

    catch(ApiException e)

    {

    return handleApiException(e);

    }

        return ok();

    }


 3) ProductService 에서 로직 추가

package com.dasdes.shopmng.domain.prdt;


import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional; //추가

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


import com.dasdes.shopmng.domain.BaseService;

import com.querydsl.core.BooleanBuilder;  //추가


import javax.inject.Inject;

import com.chequer.axboot.core.parameter.RequestParams;

import java.util.List;


import com.chequer.axboot.core.api.ApiException;



//import org.slf4j.Logger;

//import org.slf4j.LoggerFactory;


@Service

public class ProductService extends BaseService<Product, String>  {

//private final Logger logger = LoggerFactory.getLogger(ProductService.class);

    private ProductRepository productRepository;


    @Inject

    public ProductService(ProductRepository productRepository) {

        super(productRepository);

        this.productRepository = productRepository;

    }


    public List<Product> gets(RequestParams<Product> requestParams) {

    String prdtCd=requestParams.getString("prdtCd", "");

    String prdtNm=requestParams.getString("prdtNm", "");

    String filter = requestParams.getString("filter");

   

    BooleanBuilder builder = new BooleanBuilder();



        if (isNotEmpty(prdtCd)) {

            builder.and(qProduct.prdtCd.eq(prdtCd));

        }



        if (isNotEmpty(prdtNm)) {

            builder.and(qProduct.prdtNm.eq(prdtNm));

        }


        List<Product> prdtList = select().from(qProduct).where(builder).orderBy(qProduct.prdtCd.asc(), qProduct.prdtNm.asc()).fetch();


        if (isNotEmpty(filter)) {

        prdtList = filter(prdtList, filter);

        }

   

        return prdtList;

    }

    

    

    @Transactional

    public void savePrdt(List<Product> product) {

    Product prdt=null;

   

    for(int i=0;i<product.size();i++)

    {

        prdt=(Product)product.get(i);

   

        //신규추가된 데이터에 대해 기존에 있는데이터인지 체크

        if(prdt.isCreated() && exists(prdt.getId()))

        {

    throw new ApiException("신규로 추가하신 ["+prdt.getId()+"]코드는 이미 등록된 제품코드입니다.");

        }

    }

        save(product);

    }


4) 최종결과확인

  : 위와같이 소스를 수정하고 서버를 재기동 후 중복제품코드를 추가해서 입력해본다.





어때요? 도움이 많이 되셨나요? ~~~~~~~

+ Recent posts