100일 챌린지/빅데이터기반 인공지능 융합 서비스 개발자

Day 49 - Spring 5.x CRUD 프로그램 만들기

ksyke 2024. 10. 8. 17:57

1. H2 table 만들기

create table dept(
deptno int primary key auto_increment,
dname varchar(50),
loc varchar(50)
);
create table emp(
empno int primary key auto_increment,
ename varchar(50),
pay int,
hiredate date,
deptno int
);
insert into dept (dname,loc) values ('본사','서울');
insert into dept (dname,loc) values ('경남지사','경남');
insert into dept (dname,loc) values ('부산지사','부산');
commit;
insert into emp (ename,pay,hiredate,deptno) values ('user1',1000,now(),1);
insert into emp (ename,pay,hiredate,deptno) values ('user2',1000,now(),2);
insert into emp (ename,pay,hiredate,deptno) values ('user3',1000,now(),1);
insert into emp (ename,pay,hiredate,deptno) values ('user4',1000,now(),2);
commit;

2. spring legacy project

2-1. sql 폴더 만들고 sql command 저장하기

3. pom.xml 업데이트

3-1. java version up

    <properties>
        <java-version>1.8</java-version>
        <org.springframework-version>5.3.39</org.springframework-version>
        <org.aspectj-version>1.6.10</org.aspectj-version>
        <org.slf4j-version>1.6.6</org.slf4j-version>
    </properties>

    <build>
                <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
    </buid>

3-2. spring 5.3.39 version up

<org.springframework-version>5.3.39</org.springframework-version>

3-3. spring jdbc, tx, aop, test 추가

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>

3-4. aspectj weaver 추가

        <!-- AspectJ -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${org.aspectj-version}</version>
        </dependency>    
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${org.aspectj-version}</version>
        </dependency>

3-5. junit 4.13으로 버전업

        <!-- Test -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>

3-6. lombok 추가

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.34</version>
            <scope>provided</scope>
        </dependency>

3-7. mybatis spring, mybatis 추가

        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

3-8. DBCP 추가

        <!-- dbcp -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>

3-9. h2 engine 추가 (scope 삭제)

        <!-- h2 -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.200</version>
        </dependency>

4. log4j debug 모드로 수정

<!-- Application Loggers -->
<logger name="com.gimhae.day49">
<level value="debug" />
</logger>

5. applicationContext.xml (Spring bean project)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

    <bean
    class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"
    p:location="classpath:/db.properties"
    />

    <bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource"
    p:driverClassName="org.h2.Driver"
    p:url="${jdbc.url}"
    p:username="${jdbc.user}"
    p:password="${jdbc.password}"
    />

    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        p:dataSource-ref="dataSource"
    />

</beans>

5-1. JUnitTest 만들기 (ContextTest)

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
        "classpath:/applicationContext.xml"
        })
public class ContextTest {

    @Autowired
    DataSource dataSource;

    @Test
    public void test() throws SQLException {
        assertNotNull(dataSource);
        assertNotNull(dataSource.getConnection());
    }

}

6. applicationContext.xml (Spring bean project)

    ...

    <bean id="sqlSessionFactory"
    class="org.mybatis.spring.SqlSessionFactoryBean"
    p:dataSource-ref="dataSource"
    p:configLocation="classpath:/mybatis-config.xml"
    />
    <bean id="sqlSession"
    class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg ref="sqlSessionFactory"/>
    </bean>

    ...

7. db.properties & mybatis-config

jdbc.url=
jdbc.user=
jdbc.password=
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <typeAlias alias="Emp" type="com.gimhae.day49.emp.model.EmpVo"/>
        <typeAlias alias="Dept" type="com.gimhae.day49.dept.model.DeptVo"/>
    </typeAliases>
  <mappers>
    <mapper resource="mappers/DeptMapper.xml"/>
    <mapper resource="mappers/EmpMapper.xml"/>
  </mappers>
</configuration>

8. models

8-1. Vo

package com.gimhae.day49.dept.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DeptVo {
    private int deptno;
    private String dname, loc;
}

8-2. Dao (Interface)

package com.gimhae.day49.dept.model;

import java.util.List;

public interface DeptDao {
    List<DeptVo> pullList();
    DeptVo getList(int idx);
    int addList(DeptVo bean);
    int setList(DeptVo bean);
    int rmList(int idx);
}

9. mappers

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gimhae.day49.dept.model.DeptDao">
    <select id="pullList" resultType="Dept">
        select * from dept order by deptno desc
    </select>
    <select id="getList" parameterType="int" resultType="Dept">
        select * from dept where deptno=#{int}
    </select>
    <update id="addList" parameterType="Dept">
        insert into dept (dname,loc) values (#{dname},#{loc})
    </update>
    <update id="setList" parameterType="Dept">
        update dept set dname=#{dname},loc=#{loc} where deptno=#{deptno}
    </update>
    <delete id="rmList" parameterType="int">
        delete from dept where deptno=#{int}
    </delete>
</mapper>

10. servlet-context.xml

	...
	<aop:aspectj-autoproxy/>
	<tx:annotation-driven/>
...

11. DaoImplTest

package com.gimhae.day49.emp.model;

import org.junit.Before;

//@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
        "classpath:/applicationContext.xml",
        "file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"
    })
public class EmpDaoImplTest {
    @Autowired
    EmpDao empDao;
    private EmpVo target;

    @Before
    public void before() {
        target=EmpVo.builder().empno(5).ename("user5").pay(5000).deptno(1).build();

    }

    @Test
    public void test() {
        assertNotNull(empDao);
    }

    @Test
    public void testPullList() {
        assertNotNull(empDao.pullList());
    }

    @Transactional
    //rollback을 원하지 않을 때
//    @Commit 
//    @Rollback(value = false)
    @Test
    public void testAddList() {
        target.setEname("test6");
        empDao.addList(target);
    }

    @Test
    public void testGetList() {
        assertEquals(target,empDao.getList(target.getEmpno()));
    }

    @Transactional
    @Test
    public void testSetList() {
        target.setEname("tester");
        assertSame(1, empDao.setList(target));
    }

    @Transactional
    @Test
    public void testRmList() {
        assertSame(1, empDao.rmList(target.getEmpno()));
    }

}

11-1. Log Aop

package com.gimhae.day49.aop;

//@Slf4j
@Component
@Aspect
public class LogAop {
	
	@Before("execution(* com.gimhae.day49..*Impl.*(..))")
	public void before(JoinPoint join) {
		System.out.println("param:"+Arrays.toString(join.getArgs()));
	}

	@AfterReturning(
			returning = "obj",
			pointcut = "execution(* com.gimhae.day49..*Impl.*(..))")
	public void afterSuccess(Object obj) {
//		log.debug("after");
		System.out.println("return:"+obj);
	}
}

12. 서비스 만들기

12-1. Service

package com.gimhae.day49.dept.service;

@Service
public class DeptService {
    @Autowired
    SqlSession sqlSession;
    final String success="{\"result\":}";

    public List<?> list(){
        DeptDao deptDao=sqlSession.getMapper(DeptDao.class);
        return deptDao.pullList();
    }

    public DeptVo getOne(int deptno){
        DeptDao deptDao=sqlSession.getMapper(DeptDao.class);
        return deptDao.getList(deptno);
    }

    public String add(DeptVo bean){
        DeptDao deptDao=sqlSession.getMapper(DeptDao.class);
        return "{\"result\":" + deptDao.addList(bean) + "}";
    }

    public String edit(DeptVo bean){
        DeptDao deptDao=sqlSession.getMapper(DeptDao.class);
        return "{\"result\":" + deptDao.setList(bean) + "}";
    }

    public String delete(int deptno){
        DeptDao deptDao=sqlSession.getMapper(DeptDao.class);
        return "{\"result\":" + deptDao.rmList(deptno) + "}";
    }
}

12-2. Controller

package com.gimhae.day49.api;

@RestController
@RequestMapping("/api/dept/")
@RequiredArgsConstructor
public class DeptController {
    private final DeptService deptService;

    @GetMapping("")
    public List<?> list(){
        return deptService.list();
    }

    @GetMapping("/{deptno}")
    public DeptVo detail(@PathVariable int deptno) {
        return deptService.getOne(deptno);
    }

    @PostMapping(value = "",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String add(@ModelAttribute DeptVo bean) {
        return deptService.add(bean);
    }

    @PutMapping(value = "{deptno}",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String edit(@RequestBody DeptVo bean) {
        return deptService.edit(bean);
    }

    @DeleteMapping(value = "{deptno}",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String delete(@PathVariable int deptno) {
        return deptService.delete(deptno);
    }
}

13. web project 만들기

13-1. pom.xml

서블릿 업데이트

        <!-- Servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

13-2. web.xml

- schema 수정

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee                       http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">

- encoding filter 달아주기

    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/api/*</url-pattern>
    </filter-mapping>

13-3. maven update

13-4. .setting의 .xml 파일 버전 변경 (1.8/3.1)

13-5. maven update

14. API 테스트 하기

https://www.postman.com/downloads/

[Download Postman | Get Started for Free

Try Postman for free! Join 30 million developers who rely on Postman, the collaboration platform for API development. Create better APIs—faster.

www.postman.com](https://www.postman.com/downloads/)

14-1. pom.xml

jacksonbind 추가

        <!-- jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.15.2</version>
        </dependency>

api 서비스 테스트 하기

15. Rest Template 만들기