diff --git a/build.gradle b/build.gradle index 07d2578..a9340be 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,7 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.h2database:h2' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' diff --git a/sql/ddl.sql b/sql/ddl.sql new file mode 100644 index 0000000..d66d0c9 --- /dev/null +++ b/sql/ddl.sql @@ -0,0 +1,9 @@ +drop table if exists item CASCADE; +create table item +( + id bigint generated by default as identity, + name varchar(255), + price integer not null, + count integer not null, + primary key (id) +); \ No newline at end of file diff --git a/src/main/java/landvibe/springintro/aop/TimeTraceAop.java b/src/main/java/landvibe/springintro/aop/TimeTraceAop.java new file mode 100644 index 0000000..0ff28c0 --- /dev/null +++ b/src/main/java/landvibe/springintro/aop/TimeTraceAop.java @@ -0,0 +1,22 @@ +package landvibe.springintro.aop; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; +@Component +@Aspect +public class TimeTraceAop { + @Around("execution(* landvibe.springintro..*(..))") + public Object execute(ProceedingJoinPoint joinPoint) throws Throwable { + long start = System.currentTimeMillis(); + System.out.println("START : " + joinPoint.toString()); + try { + return joinPoint.proceed(); // 다음 메소드가 진행 + } finally { + long finish = System.currentTimeMillis(); + long timeMs = finish - start; + System.out.println("END : " + joinPoint.toString() + " " + timeMs + + "ms"); // 어떤 메소드를 call 했는지 + } + } +} \ No newline at end of file diff --git a/src/main/java/landvibe/springintro/controller/HelloController.java b/src/main/java/landvibe/springintro/controller/HelloController.java new file mode 100644 index 0000000..6ff23f8 --- /dev/null +++ b/src/main/java/landvibe/springintro/controller/HelloController.java @@ -0,0 +1,51 @@ +package landvibe.springintro.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class HelloController { + @GetMapping("hello") + public String hello(Model model){ + model.addAttribute("data","LandVibe"); + return "hello"; + } + + @GetMapping("hello-mvc") + public String helloMvc( + @RequestParam(value="name", required=false, defaultValue= + "landVibe") String name, + Model model){ + model.addAttribute("name",name); + return "hello-template"; + } + + @GetMapping("hello-string") + @ResponseBody + public String helloString(@RequestParam("name") String name){ + return "hello " + name; + } + + @GetMapping("hello-api") + @ResponseBody + public Hello helloApi(@RequestParam("name") String name){ + Hello hello = new Hello(); + hello.setName(name); + return hello; + } + + static class Hello{ + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} diff --git a/src/main/java/landvibe/springintro/controller/HomeController.java b/src/main/java/landvibe/springintro/controller/HomeController.java new file mode 100644 index 0000000..b3bdfb8 --- /dev/null +++ b/src/main/java/landvibe/springintro/controller/HomeController.java @@ -0,0 +1,12 @@ +package landvibe.springintro.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class HomeController { + @GetMapping("/") + public String home(){ + return "home"; + } +} diff --git a/src/main/java/landvibe/springintro/controller/ItemController.java b/src/main/java/landvibe/springintro/controller/ItemController.java new file mode 100644 index 0000000..07b9228 --- /dev/null +++ b/src/main/java/landvibe/springintro/controller/ItemController.java @@ -0,0 +1,47 @@ +package landvibe.springintro.controller; + +import landvibe.springintro.item.service.ItemService; +import landvibe.springintro.item.domain.Item; +import landvibe.springintro.item.service.ItemService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; + +import java.util.List; + +@Controller +public class ItemController { + private final ItemService itemService; + + @Autowired + public ItemController(ItemService itemService) { + this.itemService = itemService; + } + + @GetMapping("/items/new") + public String createForm(){ + return "items/createForm"; + } + + @PostMapping("/items/new") + public String create(@ModelAttribute ItemCreateForm form){ + Item item = new Item(); + item.setName(form.getName()); + item.setPrice(form.getPrice()); + item.setCount(form.getCount()); + itemService.create(item); + + return "redirect:/"; + } + + @GetMapping("/items") + public String list(Model model){ + List items = itemService.findItems(); + model.addAttribute("items", items); + return "items/itemList"; + } + +} diff --git a/src/main/java/landvibe/springintro/controller/ItemCreateForm.java b/src/main/java/landvibe/springintro/controller/ItemCreateForm.java new file mode 100644 index 0000000..1859669 --- /dev/null +++ b/src/main/java/landvibe/springintro/controller/ItemCreateForm.java @@ -0,0 +1,31 @@ +package landvibe.springintro.controller; + +public class ItemCreateForm { + private String name; + private Integer price; + private Integer count; + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } + + public Integer getPrice() { + return price; + } + + public void setPrice(Integer price) { + this.price = price; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/landvibe/springintro/item/config/ItemConfig.java b/src/main/java/landvibe/springintro/item/config/ItemConfig.java new file mode 100644 index 0000000..c93d5c1 --- /dev/null +++ b/src/main/java/landvibe/springintro/item/config/ItemConfig.java @@ -0,0 +1,42 @@ +package landvibe.springintro.item.config; + +import jakarta.persistence.EntityManager; +import landvibe.springintro.item.repository.*; +import landvibe.springintro.item.service.ItemService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +@Configuration +public class ItemConfig { + private final DataSource dataSource; +// +// @Autowired +// public ItemConfig(DataSource dataSource, EntityManager em) { +// this.dataSource = dataSource; +// this.em = em; +// } + + public ItemConfig(DataSource dataSource) { + this.dataSource = dataSource; + } + +/* private final ItemRepository itemRepository; + public ItemConfig(ItemRepository itemRepository){ + this.itemRepository = itemRepository; + }*/ + @Bean + public ItemService itemService(){ + return new ItemService(itemRepository()); + } + + @Bean + public ItemRepository itemRepository(){ + //return new MemoryItemRepository(); + //return new JdbcItemRepository(dataSource); + return new JdbcTemplateItemRepository(dataSource); + //return new JpaItemRepository(em); + } +} diff --git a/src/main/java/landvibe/springintro/item/domain/Item.java b/src/main/java/landvibe/springintro/item/domain/Item.java new file mode 100644 index 0000000..9e437e5 --- /dev/null +++ b/src/main/java/landvibe/springintro/item/domain/Item.java @@ -0,0 +1,48 @@ +package landvibe.springintro.item.domain; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class Item { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String name; + private Integer price; + private Integer count; + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } + + public Integer getPrice() { + return price; + } + + public void setPrice(Integer price) { + this.price = price; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/src/main/java/landvibe/springintro/item/repository/ItemRepository.java b/src/main/java/landvibe/springintro/item/repository/ItemRepository.java new file mode 100644 index 0000000..ca71d6c --- /dev/null +++ b/src/main/java/landvibe/springintro/item/repository/ItemRepository.java @@ -0,0 +1,13 @@ +package landvibe.springintro.item.repository; + +import landvibe.springintro.item.domain.Item; + +import java.util.List; +import java.util.Optional; + +public interface ItemRepository { + Item save(Item item); + Optional findById(Long id); + Optional findByName(String name); + List findAll(); +} diff --git a/src/main/java/landvibe/springintro/item/repository/JdbcItemRepository.java b/src/main/java/landvibe/springintro/item/repository/JdbcItemRepository.java new file mode 100644 index 0000000..b89477d --- /dev/null +++ b/src/main/java/landvibe/springintro/item/repository/JdbcItemRepository.java @@ -0,0 +1,148 @@ +package landvibe.springintro.item.repository; +import landvibe.springintro.item.domain.Item; +import org.springframework.jdbc.datasource.DataSourceUtils; +import javax.sql.DataSource; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +public class JdbcItemRepository implements ItemRepository { + private final DataSource dataSource; + public JdbcItemRepository(DataSource dataSource) { + this.dataSource = dataSource; + } + @Override + public Item save(Item item) { + String sql = "insert into item(name, price, count) values(?, ?, ?)"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); + pstmt.setString(1, item.getName()); + pstmt.setInt(2, item.getPrice()); + pstmt.setInt(3, item.getCount()); + pstmt.executeUpdate(); + rs = pstmt.getGeneratedKeys(); + if (rs.next()) { + item.setId(rs.getLong(1)); + } else { + throw new SQLException("id 조회 실패"); + } + return item; + } catch (Exception e) { + throw new IllegalStateException(e); + } finally { + close(conn, pstmt, rs); + } + } + @Override + public Optional findById(Long id) { + String sql = "select * from item where id = ?"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql); + pstmt.setLong(1, id); + rs = pstmt.executeQuery(); + if (rs.next()) { + Item item = new Item(); + item.setId(rs.getLong("id")); + item.setName(rs.getString("name")); + item.setCount(rs.getInt("count")); + item.setPrice(rs.getInt("price")); + return Optional.of(item); + } else { + return Optional.empty(); + } + } catch (Exception e) { + throw new IllegalStateException(e); + } finally { + close(conn, pstmt, rs); + } + } + @Override + public Optional findByName(String name) { + String sql = "select * from item where name = ?"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql); + pstmt.setString(1, name); + rs = pstmt.executeQuery(); + if (rs.next()) { + Item item = new Item(); + item.setId(rs.getLong("id")); + item.setName(rs.getString("name")); + item.setCount(rs.getInt("count")); + item.setPrice(rs.getInt("price")); + return Optional.of(item); + } + return Optional.empty(); + } catch (Exception e) { + throw new IllegalStateException(e); + } finally { + close(conn, pstmt, rs); + } + } + @Override + public List findAll() { + String sql = "select * from item"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql); + rs = pstmt.executeQuery(); + List items = new ArrayList<>(); + while (rs.next()) { + Item item = new Item(); + item.setId(rs.getLong("id")); + item.setName(rs.getString("name")); + item.setCount(rs.getInt("count")); + item.setPrice(rs.getInt("price")); + items.add(item); + } + return items; + } catch (Exception e) { + throw new IllegalStateException(e); + } finally { + close(conn, pstmt, rs); + } + } + private Connection getConnection() { + return DataSourceUtils.getConnection(dataSource); + } + private void close(Connection conn, PreparedStatement pstmt, ResultSet rs) { + try { + if (rs != null) { + rs.close(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + try { + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + try { + if (conn != null) { + close(conn); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + private void close(Connection conn) throws SQLException { + DataSourceUtils.releaseConnection(conn, dataSource); + } +} \ No newline at end of file diff --git a/src/main/java/landvibe/springintro/item/repository/JdbcTemplateItemRepository.java b/src/main/java/landvibe/springintro/item/repository/JdbcTemplateItemRepository.java new file mode 100644 index 0000000..c3f27a8 --- /dev/null +++ b/src/main/java/landvibe/springintro/item/repository/JdbcTemplateItemRepository.java @@ -0,0 +1,54 @@ +package landvibe.springintro.item.repository; +import landvibe.springintro.item.domain.Item; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import javax.sql.DataSource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +public class JdbcTemplateItemRepository implements ItemRepository { + private final JdbcTemplate jdbcTemplate; + public JdbcTemplateItemRepository(DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + } + @Override + public Item save(Item item) { + SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate); + jdbcInsert.withTableName("item").usingGeneratedKeyColumns("id"); + Map parameters = new HashMap<>(); + parameters.put("name", item.getName()); + parameters.put("count", item.getCount()); + parameters.put("price", item.getPrice()); + Number key = jdbcInsert.executeAndReturnKey(new + MapSqlParameterSource(parameters)); + item.setId(key.longValue()); + return item; + } + @Override + public Optional findById(Long id) { + List result = jdbcTemplate.query("select * from item where id = ? ", rowMapper(), id); + return result.stream().findAny(); + } + @Override + public Optional findByName(String name) { + List result = jdbcTemplate.query("select * from item where name = ? ", rowMapper(), name); + return result.stream().findAny(); + } + @Override + public List findAll() { + return jdbcTemplate.query("select * from item", rowMapper()); + } + private RowMapper rowMapper() { + return (rs, rowNum) -> { + Item item = new Item(); + item.setId(rs.getLong("id")); + item.setName(rs.getString("name")); + item.setPrice(rs.getInt("price")); + item.setCount(rs.getInt("count")); + return item; + }; + } +} \ No newline at end of file diff --git a/src/main/java/landvibe/springintro/item/repository/JpaItemRepository.java b/src/main/java/landvibe/springintro/item/repository/JpaItemRepository.java new file mode 100644 index 0000000..57e6a77 --- /dev/null +++ b/src/main/java/landvibe/springintro/item/repository/JpaItemRepository.java @@ -0,0 +1,34 @@ +package landvibe.springintro.item.repository; +import jakarta.persistence.EntityManager; +import landvibe.springintro.item.domain.Item; +import java.util.List; +import java.util.Optional; +public class JpaItemRepository implements ItemRepository { + private final EntityManager em; + public JpaItemRepository(EntityManager em) { + this.em = em; + } + @Override + public Item save(Item item) { + em.persist(item); + return item; + } + @Override + public Optional findById(Long id) { + Item item = em.find(Item.class, id); + return Optional.ofNullable(item); + } + @Override + public Optional findByName(String name) { + return em.createQuery("select i from Item i where i.name = :name", + Item.class) + .setParameter("name", name) + .getResultStream() + .findAny(); + } + @Override + public List findAll() { + return em.createQuery("select i from Item i", Item.class) + .getResultList(); + } +} \ No newline at end of file diff --git a/src/main/java/landvibe/springintro/item/repository/MemoryItemRepository.java b/src/main/java/landvibe/springintro/item/repository/MemoryItemRepository.java new file mode 100644 index 0000000..68b589c --- /dev/null +++ b/src/main/java/landvibe/springintro/item/repository/MemoryItemRepository.java @@ -0,0 +1,39 @@ +package landvibe.springintro.item.repository; + +import landvibe.springintro.item.domain.Item; +import org.springframework.stereotype.Repository; + +import java.util.*; + +public class MemoryItemRepository implements ItemRepository{ + private static Map store = new HashMap<>(); + private static long sequence = 0L; + + @Override + public Item save(Item item) { + item.setId(++sequence); + store.put(item.getId(),item); + return item; + } + + @Override + public Optional findById(Long id) { + return Optional.ofNullable(store.get(id)); + } + + @Override + public Optional findByName(String name) { + return store.values().stream() + .filter(item->item.getName().equals(name)) + .findAny(); + } + + @Override + public List findAll() { + return new ArrayList<>(store.values()); + } + + public void clearStore(){ + store.clear(); + } +} diff --git a/src/main/java/landvibe/springintro/item/repository/SpringDataJpaMemberRepository.java b/src/main/java/landvibe/springintro/item/repository/SpringDataJpaMemberRepository.java new file mode 100644 index 0000000..a42e702 --- /dev/null +++ b/src/main/java/landvibe/springintro/item/repository/SpringDataJpaMemberRepository.java @@ -0,0 +1,12 @@ +package landvibe.springintro.item.repository; + +import landvibe.springintro.item.domain.Item; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface SpringDataJpaMemberRepository extends JpaRepository, ItemRepository { + @Override + Optional findByName(String name); +} diff --git a/src/main/java/landvibe/springintro/item/service/ItemService.java b/src/main/java/landvibe/springintro/item/service/ItemService.java new file mode 100644 index 0000000..34c64d4 --- /dev/null +++ b/src/main/java/landvibe/springintro/item/service/ItemService.java @@ -0,0 +1,42 @@ +package landvibe.springintro.item.service; + +import landvibe.springintro.item.domain.Item; +import landvibe.springintro.item.repository.ItemRepository; +import landvibe.springintro.item.repository.MemoryItemRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Transactional +public class ItemService { + private final ItemRepository repository; + public ItemService(ItemRepository repository){ + this.repository = repository; + } + + /** + * 상품 등록 + */ + public Long create(Item item){ + long start = System.currentTimeMillis(); + try { + validateDuplicateItem(item.getName()); + repository.save(item); + return item.getId(); + } finally { + long end = System.currentTimeMillis(); + long timeMs = end - start; + System.out.println("create::timeMs = " + timeMs); + } + } + public List findItems(){ + return repository.findAll(); + } + public void validateDuplicateItem(String itemName){ + repository.findByName(itemName) + .ifPresent(i->{ + throw new IllegalArgumentException("이미 존재하는 상품입니다."); + }); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e7c1e8f..267d0f0 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,7 @@ spring.application.name=springintro +server.port=8080 +spring.datasource.url=jdbc:h2:tcp://localhost/~/test +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.username=sa +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=none diff --git a/src/main/resources/templates/items/createForm.html b/src/main/resources/templates/items/createForm.html index 6331260..48171c3 100644 --- a/src/main/resources/templates/items/createForm.html +++ b/src/main/resources/templates/items/createForm.html @@ -26,4 +26,4 @@ - + \ No newline at end of file diff --git a/src/main/resources/templates/items/itemList.html b/src/main/resources/templates/items/itemList.html old mode 100755 new mode 100644 index 28a34de..220f018 --- a/src/main/resources/templates/items/itemList.html +++ b/src/main/resources/templates/items/itemList.html @@ -36,4 +36,4 @@ - + \ No newline at end of file diff --git a/src/test/java/landvibe/springintro/item/repository/MemoryItemRepositoryTest.java b/src/test/java/landvibe/springintro/item/repository/MemoryItemRepositoryTest.java new file mode 100644 index 0000000..4409341 --- /dev/null +++ b/src/test/java/landvibe/springintro/item/repository/MemoryItemRepositoryTest.java @@ -0,0 +1,79 @@ +package landvibe.springintro.item.repository; + +import landvibe.springintro.item.domain.Item; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + + +import java.util.List; + +import static org.assertj.core.api.Assertions.*; + +class MemoryItemRepositoryTest { + MemoryItemRepository repository = new MemoryItemRepository(); + @AfterEach + void afterEach(){ + repository.clearStore(); + } + + @Test + void save() { + //given + Item item = createItem("과자", 10, 1000); + + //when + repository.save(item); + + //then + Item foundItem = repository.findById(item.getId()).get(); + assertThat(foundItem).isEqualTo(item); + } + + @Test + void findById() { + Item 포카칩 = createItem("포카칩",10,1000); + repository.save(포카칩); + Item foundItem = repository.findById(포카칩.getId()).get(); + assertThat(foundItem).isEqualTo(포카칩); + } + + @Test + void findByName() { + //given + Item 눈을감자 = createItem("눈을감자",10,1000); + Item 프링글스 = createItem("프링글스",10,1000); + repository.save(눈을감자); + repository.save(프링글스); + + //when + Item foundItem = repository.findByName("눈을감자").get(); + + //then + assertThat(foundItem).isEqualTo(눈을감자); + } + + @Test + void findAll() { + //given + Item 눈을감자 = createItem("눈을감자",10,1000); + Item 프링글스 = createItem("프링글스",10,1000); + repository.save(눈을감자); + repository.save(프링글스); + + //when + List foundItems = repository.findAll(); + + //then + assertThat(foundItems.size()).isEqualTo(2); + assertThat(foundItems).contains(눈을감자,프링글스); + } + + private static Item createItem(String name, int count, int price){ + Item item = new Item(); + item.setName(name); + item.setCount(count); + item.setPrice(price); + return item; + } + +} \ No newline at end of file diff --git a/src/test/java/landvibe/springintro/item/service/ItemServiceTest.java b/src/test/java/landvibe/springintro/item/service/ItemServiceTest.java new file mode 100644 index 0000000..5a817aa --- /dev/null +++ b/src/test/java/landvibe/springintro/item/service/ItemServiceTest.java @@ -0,0 +1,67 @@ +package landvibe.springintro.item.service; + +import landvibe.springintro.item.domain.Item; +import landvibe.springintro.item.repository.ItemRepository; +import landvibe.springintro.item.repository.MemoryItemRepository; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@Transactional +class ItemServiceTest { + @Autowired + ItemService service; + @Autowired + ItemRepository repository; + +// @BeforeEach +// void setUp(){ +// repository = new MemoryItemRepository(); +// service = new ItemService(repository); +// } +// @AfterEach +// void tearDown(){ +// repository.clearStore(); +// } + + @Test + public void 상품생성() throws Exception{ + //given + Item item = createItem("눈을감자",10,1000); + + //when + Long id = service.create(item); + + //then + Item foundItem = repository.findById(id).get(); + assertThat(foundItem).isEqualTo(item); + } + + @Test + void 중복이름_상품예외(){ + //given + Item item = createItem("눈을감자",10,1000); + Item duplicatedItem = createItem("눈을감자",10,1000); + service.create(item); + + //when & then + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, + ()->service.create(duplicatedItem)); //예외발생 + assertThat(ex.getMessage()).isEqualTo("이미 존재하는 상품입니다."); + } + + private static Item createItem(String name, int count, int price){ + Item item = new Item(); + item.setName(name); + item.setCount(count); + item.setPrice(price); + return item; + } +} \ No newline at end of file diff --git a/top:/localhost/~/test.mv.db b/top:/localhost/~/test.mv.db new file mode 100644 index 0000000..486313b Binary files /dev/null and b/top:/localhost/~/test.mv.db differ diff --git a/top:/localhost/~/test.trace.db b/top:/localhost/~/test.trace.db new file mode 100644 index 0000000..8a00eec --- /dev/null +++ b/top:/localhost/~/test.trace.db @@ -0,0 +1,147 @@ +2024-07-22 06:27:39.670699+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item where name = ? [42104-224] +2024-07-22 06:28:14.551115+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item where name = ? [42104-224] +2024-07-22 06:28:18.915254+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:28:51.473506+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:30:41.779646+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item where name = ? [42104-224] +2024-07-22 06:30:44.090861+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:30:47.126538+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:31:13.251692+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:31:13.789977+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:31:43.472163+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:31:48.061998+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:32:26.908583+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:34:53.080648+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:38:23.940611+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:38:27.673013+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:38:31.607213+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:40:51.995039+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 06:40:55.172849+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224] +2024-07-22 12:56:29.095268+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 12:56:29.723690+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 12:56:32.464725+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 12:56:41.789791+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 12:57:15.786025+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 12:57:18.039077+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 12:57:19.600663+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 13:01:45.983813+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 13:14:22.558281+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 13:33:15.687339+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:02:03.877594+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:37:55.046655+09:00 jdbc[13]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:38:22.206815+09:00 jdbc[13]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:39:39.582182+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:39:39.768284+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:39:43.516229+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:45:23.362213+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:45:27.304265+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:46:20.284427+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:47:25.858248+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:47:26.758774+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:48:14.730746+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:48:33.030285+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:48:39.373925+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:50:25.488381+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 14:50:43.856552+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 15:27:26.001008+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 15:27:29.653356+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 15:30:08.541652+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 15:32:11.515399+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select i1_0.id,i1_0.count,i1_0.name,i1_0.price from item i1_0 [42104-224] +2024-07-22 15:34:07.024311+09:00 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" not found (this database is empty); SQL statement: +select * from item [42104-224]