Product. TEST_20220418


  • TESTは郵便配達員の代わりに使用される
  • ProductRepository.java
  • package com.example.repository;
    
    import com.example.entity.ProductEntity;
    
    import org.springframework.data.repository.CrudRepository;
    import org.springframework.stereotype.Repository;
    
    @Repository
    // crud는 기본적인 것들만 들어있음. Jpa 쓰는게 좋을듯?
    public interface ProductRepository extends CrudRepository<ProductEntity, Long> {
    }
  • ProductService.java
  • package com.example.service;
    
    import java.util.List;
    
    import com.example.entity.ProductEntity;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public interface ProductService {
        
        public int insertBatch(List<ProductEntity> product);
    }
  • ProductServiceImpl.java
  • package com.example.service;
    
    import java.util.List;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    
    import com.example.entity.ProductEntity;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    public class ProductServiceImpl implements ProductService{
        
        @Autowired EntityManagerFactory emf;
    
        @Override
        public int insertBatch(List<ProductEntity> list) {
            EntityManager em = emf.createEntityManager();
            try {
                em.getTransaction().begin();
                for(ProductEntity prd: list) {
                    em.persist(prd);
                }
                em.getTransaction().commit();
                return 1;
            } catch (Exception e) {
                e.printStackTrace();
                em.getTransaction().rollback();
                return 0;
            }
        }
    }
    ProductRestController.java
    package com.example.restcontroller;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import com.example.entity.ProductEntity;
    import com.example.repository.ProductRepository;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.MediaType;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    @RestController
    
    // API를 설정하지 않으면 스마트폰 앱으로 만들 경우 앱에서 데이터를 가져갈 수 없음.(포스트맨은 그래도 됨)
    @CrossOrigin("*") 
    @RequestMapping(value = "/api/product")
    public class ProductRestController {
    
        @Autowired ProductRepository pRepository;
    
        // 127.0.0.1:9090/ROOT/api/product/insert.json
        @PostMapping(
            value = "/insert.json",
            consumes = { MediaType.ALL_VALUE },
            produces = { MediaType.APPLICATION_JSON_VALUE })
            
        public Map<String, Object> insertPOST(
            @ModelAttribute ProductEntity product,
            // required = false => 이미지 첨부 해도 되고 안해도 된다
            @RequestParam(name = "file", required = false) MultipartFile file) {
            Map<String, Object> map = new HashMap<String, Object>();
            try {
                if(file != null) {
                    if(!file.isEmpty()) {
                        product.setImagedata(file.getBytes());
                        product.setImagename(file.getOriginalFilename());
                        product.setImagetype(file.getContentType());
                        product.setImagesize(file.getSize());
                    }
                }
                pRepository.save(product);
                map.put("status", 200);
            } catch (Exception e) {
                e.printStackTrace();
                map.put("status", 0);
            }
            return map;
        }
    
        // 저장소를 이용하지 못함. 서비스를 써야함
        @PostMapping(
            value = "/insertbatch.json",
            consumes = { MediaType.ALL_VALUE },
            produces = { MediaType.APPLICATION_JSON_VALUE })
            
        public Map<String, Object> insertbatchPOST(
            // 배열은 Modelattribute 못씀
            @RequestParam(name = "name") String[] name,
            @RequestParam(name = "price") String[] price,
            // required = false => 이미지 첨부 해도 되고 안해도 된다
            @RequestParam(name = "file") MultipartFile file) {
            Map<String, Object> map = new HashMap<String, Object>();
            try {
                List<ProductEntity> list = new ArrayList<>();
    
                // 서비스를 사용하지 않고 하는 방법
                pRepository.saveAll(list);
    
                map.put("status", 200);
            } catch (Exception e) {
                e.printStackTrace();
                map.put("status", 0);
            }
            return map;
        }
    
        @PutMapping(
            value = "/update.json", 
            consumes = { MediaType.ALL_VALUE },
            produces = { MediaType.APPLICATION_JSON_VALUE })
    
        public Map<String, Object> updatebatch(
                @RequestBody ProductEntity product) {
                Map<String, Object> map = new HashMap<String, Object>();
            try {
                // 1개 꺼내기
                ProductEntity product1 = pRepository.findById(product.getNo()).orElse(null);
    
                // 필요정보 변경
                product1.setName(product.getName());
                product1.setPrice(product.getPrice());
                pRepository.save(product1);
                map.put("status", 200);
            } catch (Exception e) {
                e.printStackTrace();
                map.put("status", 0);
            }
            return map;
        }
    }
    ProductEntity.java
    package com.example.entity;
    
    import java.util.Date;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.Lob;
    import javax.persistence.SequenceGenerator;
    import javax.persistence.Table;
    
    import org.hibernate.annotations.UpdateTimestamp;
    import org.springframework.format.annotation.DateTimeFormat;
    
    import lombok.Data;
    
    @Data
    @Entity
    @Table(name = "PRODUCT")
    @SequenceGenerator(
        name = "SEQ3", 
        sequenceName = "SEQ_PRODUCT_NO", 
        allocationSize = 1,
        initialValue = 1001
        )
    public class ProductEntity {
        
        @Id
        @GeneratedValue(generator = "SEQ3", strategy = GenerationType.SEQUENCE)
        Long no;
    
        @Column(length = 250)
        String name;
    
        Long price;
    
        @Lob
        @Column(nullable = true)
        byte[] imagedata;
    
        String imagename;
    
        String imagetype;
    
        Long imagesize = 0L;
    
        // updatetimestamp => 변경 될때도 날짜 바뀜
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
        @UpdateTimestamp // CURRENT_DATE
        Date uptdate;
    }
  • TEST!. ProductRestControllerTest.java
  • package com.example;
    
    import org.springframework.http.HttpEntity;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.util.LinkedMultiValueMap;
    import org.springframework.util.MultiValueMap;
    import org.springframework.web.client.RestTemplate;
    
    import static org.assertj.core.api.Assertions.assertThat;
    
    import com.example.entity.ProductEntity;
    
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.BeforeEach;
    
    public class ProductRestControllerTest {
        
        RestTemplate restTemplate;
    
        @BeforeEach
        public void setup() {
            restTemplate = new RestTemplate();
        }
    
        // http://127.0.0.1:9090/ROOT/api/product/insert.json
        // @ModelAttribute
        @Test
        public void insertTest() {
            MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
            body.add("name", "테스트용");
            body.add("price", 1234L);
    
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    
            HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(body, headers);
            ResponseEntity<String> result = restTemplate.exchange("http://127.0.0.1:9090/ROOT/api/product/insert.json",
            HttpMethod.POST, entity, String.class);
    
            assertThat(result.getStatusCode().toString()).isEqualTo("200 OK");
        }
    
        // http://127.0.0.1:9090/ROOT/api/product/update.json
        // @RequestBody
        @Test
        public void PatchTest() {
            ProductEntity product = new ProductEntity();
            product.setNo(1001L);
            product.setName("솔");
            product.setPrice(5353L);
    
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
    
            HttpEntity<ProductEntity> entity = new HttpEntity<>(product, headers);
            ResponseEntity<String> result = restTemplate.exchange("http://127.0.0.1:9090/ROOT/api/product/update.json",
            HttpMethod.PUT, entity, String.class);
    
            assertThat(result.getStatusCode().toString()).isEqualTo("200 OK");
        }
    }
  • Product.vue
  • <template>
        <div>
            <el-card class="fade-in-left" shadow="always">
                <h3>product</h3>
                <hr />
    
                <el-form>
                    <el-form-item label="제품명: " label-width="120px">
                        <el-input type="text" v-model="state.name" style="width:192px"/>
                    </el-form-item>
    
                    <el-form-item label="가격: " label-width="120px">
                        <el-input type="text" v-model="state.price" style="width:192px"/>
                    </el-form-item>
    
                    <el-image :src="state.imageUrl" style="width: 50px; margin-left: 120px;" />
    
                    <el-form-item label="이미지: " label-width="120px">
                        <input type="file" style="width:192px" @change="handleImage($event)" />
                    </el-form-item>
                </el-form>
                <el-button style="margin-left: 120px" @click="handleInsert" >등록하기</el-button>
            </el-card>
    
            <el-card class="fade-in-left" shadow="always">
                <div v-for="(tmp, idx) in 2" :key = "tmp" >
                    <el-form>
                        <el-form-item label="제품명: " label-width="120px">
                            <el-input type="text" v-model="state.name1[idx]" style="width:192px"/>
                        </el-form-item>
    
                        <el-form-item label="가격: " label-width="120px">
                            <el-input type="text" v-model="state.price1[idx]" style="width:192px"/>
                        </el-form-item>
    
                        <el-image :src="state.imageUrl1[idx]" style="width: 50px; margin-left: 120px;" />
    
                        <el-form-item label="이미지: " label-width="120px">
                            <input type="file" style="width:192px" @change="handleImage1($event, idx)" />
                        </el-form-item>
                    </el-form>
                </div>
                <el-button style="margin-left: 120px" @click="handleInsert1" >등록하기1</el-button>
            </el-card>
        </div>
    </template>
    
    <script>
    import { reactive } from 'vue'
    import axios from 'axios';
    export default {
        setup () {
            const state = reactive({
                name     : '',
                price    : '',
                imageUrl : require('../assets/logo.png'),
                imageFile: null,
    
                name1     : ['', ''],
                price1    : ['', ''],
                imageUrl1 : [require('../assets/logo.png'), require('../assets/logo.png')],
                imageFile1: []
            });
    
            const handleImage = (e) => {
                if(e.target.files[0]) {
                    state.imageUrl = URL.createObjectURL(e.target.files[0])
                    state.imageFile = e.target.files[0];
                } else {
                    state.imageUrl = require('../assets/logo.png');
                    state.imageFile = null;
                }
            }
    
            const handleImage1 = (e, idx) => {
                if(e.target.files[0]) {
                    state.imageUrl1[idx] = URL.createObjectURL(e.target.files[0])
                    state.imageFile1[idx] = e.target.files[0];
                } else {
                    state.imageUrl1[idx] = require('../assets/logo.png');
                    state.imageFile1[idx] = null;
                }
            }
    
            const handleInsert = async() => {
                const url = `/ROOT/api/product/insert.json`;
                const headers = { "Content-Type": "form-data" };
                const body = new FormData();
                body.append("name", state.name);
                body.append("price", state.price);
                body.append("file", state.imageFile);
    
                const response = await axios.post(url, body, { headers });
                console.log(response.data);
            }
    
            const handleInsert1 = async() => {
                const url = `/ROOT/api/product/insertbatch.json`;
                const headers = { "Content-Type": "form-data" };
                const body = new FormData();
                for(let i=0; i<state.name1.length; i++) {
                    body.append("name", state.name1[i]);
                    body.append("price", state.price1[i]);
    
                    body.append("file", state.imageFile1[i]);
                }
    
                const response = await axios.post(url, body, { headers });
                console.log(response.data);
            }
    
            return { state, handleImage, handleImage1, handleInsert, handleInsert1 }
        }
    }
    </script>
    
    <style lang="scss" scoped>
        @import url(../assets/css/mystyle.css);
    </style>