본문 바로가기

Back-end(Spring Framework)/필기일지

231204 [Back-end] Spring Framework/ Spring Legacy Project MVC 실습/ JDBC(스프링 프레임워크)/ mysql-connector-java를 이용한 java-mysql 연동

[23.12.04]  80차 

 

<<진도>>

[Back-end] Spring Framework

/ Spring Legacy Project  MVC 실습

/ JDBC(스프링 프레임워크)

/ mysql-connector-java를 이용한 java-mysql 연동

 

<<오늘의 팁>>

- Error 500번대는 server의 문제  / 400번대는 client의 문제

- Spring Framework는 @Autowired 가 없으면 자동 주입이 되지 않는다.(DI 시 생성자에 어노테이션 필수)- 참조형 Long의 초기값은 null !

- (복사한 프로젝트)계층 구조 마지막 이름(ver2)과 context(ver2copy) 가 같은 필요는 없다.


 

[ Spring Framework ]

< 과제 풀이 >

 

	<%
	String context = request.getContextPath(); 
	System.out.println("[회원가입 view] context : " + context); //: /ver2
	%>

	<form action="<%=context %>/member/new" method="post">
		<label for="name">이름 : </label>
		<input type="text" name="name" id="name" placeholder="이름을 입력하세요...">
		<input type= "submit" value="입력완료">
	</form>

 

: POST방식 요청에 redirect:/ 시 GET방식 요청이된다.

 

[ PRG패턴 ]

Post Redirect Get

POST 요청이 오면 해당 요청을 수행한 후 

Redirect를 시켜서

GET 요청으로 변환시켜는 다시 요청시키는 행위를 의미

	@RequestMapping(value = "/new", method = RequestMethod.POST)
	public String create(@RequestParam String name) {
		Member member = new Member();
		member.setName(name);
		repository.save(member);
		return "redirect:/";
	}

 

 

Controller에 Repository 생성자 통해 의존성주입 후

 

/ MemberMemoryRepository - save()

@Repository 
public class MemberMemoryRepository implements MemberRepository {

	private static Map<Long, Member> store = new HashMap<Long, Member>();
	private static Long sequence = 0L;

	@Override
	public Member save(Member member) {
		member.setId(++sequence);
		store.put(member.getId(), member);
		return member;
	}

 

/ MemberController - create()

	@RequestMapping(value = "/new", method = RequestMethod.POST)
	public String create(@ModelAttribute Member member) {
		repository.save(member);
		return "redirect:/";
	}

 

 

/ MemberMemoryRepositsssory - findAll()

	@Override
	public List<Member> findAll() {
		return new ArrayList<Member>(store.values());	
	}

 

/ MemberController.java - memberList

	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String memberList(Model model) {
		List<Member> members = repository.findAll();
		model.addAttribute("members", members);
		return "member/memberList";
	}

 

/ memberList.jsp

		<%
		List<Member> members = (List<Member>)request.getAttribute("members");
		%>
		
		<table>
			<thead>
				<tr>
					<td>번호</td>
					<td>이름</td>
				</tr>
			</thead>
			<tbody>
				<%for(Member member : members){%>
				<tr>
					<td><%=member.getId() %> </td>	
					<td><%=member.getName() %></td>		
				</tr>
				<%} %>
			</tbody>
		</table>

 


** Lambda식은 자바 1.8ver 이상부터 지원, 프로젝트 properties

 

- 기본 lib를 사용하는 11버전으로 설정 후

 

- project Facets에서도 자바버전 설정

 

- pom.xml에서 프로젝트의 전체 java버전 코드수정을 해준다

: Spring Framework에서는 자바버전관리를 수동으로 해줘야함

(Spring Boot에서는 build.gradle에서  starter를 통해 jre/ java 버전관리를 자동으로 해준다)

 

- 또한 pom.xml에서 java버전과 spring버전을 맞춰줄 필요가있다.

(jdk 11은 최소 spring 5.1 이상버전 사용해야 한다)

참고. https://docs.spring.io/spring-framework/docs/5.2.25.RELEASE/spring-framework-reference/overview.html#overview-spring

 

 

Spring Framework Overview

Spring makes it easy to create Java enterprise applications. It provides everything you need to embrace the Java language in an enterprise environment, with support for Groovy and Kotlin as alternative languages on the JVM, and with the flexibility to crea

docs.spring.io

참고.&nbsp;https://docs.spring.io/spring-framework/docs/5.2.25.RELEASE/spring-framework-reference/overview.html#overview-spring

 

Maven 버전도&nbsp; 3.1.1.RELEASE

POM.xml 코드 수정 시 Maven 버전도 모두 업데이트 된다.

pom.xml (Overview, Dependencies)에서 버전 체크 가능


[memberSearch]

 

/ MemberMemoryRepository

	@Override
	public Optional<Member> findById(Long id) {
		return Optional.ofNullable(store.get(id));
	}
	
	@Override
	public Optional<Member> findByName(String name) {
		return store.values().stream()
				.filter(n -> n.getName().equals(name))
				.findAny();
	}

 

/ MemberController

	@RequestMapping(value = "/search", method = RequestMethod.GET)
	public String memberSearch(@ModelAttribute Member member, Model model) {
		Member searchMember = new Member();
	
		if(member.getId() != null)
			searchMember = repository.findById(member.getId()).get();
		else if(!member.getName().isEmpty())
			searchMember = repository.findByName(member.getName()).get();
		
		model.addAttribute("member", searchMember);
		
		return "member/search";
	}

 

 

/ search.jsp

	<!-- EL 활용  -->
	<h1>검색 결과</h1>
	<div>
		<span>아이디 : </span>
		<span>${ member.id }</span>
	</div>
	<div>
		<span>이름 : </span>
		<span>${ member.name }</span>
	</div>

 


스프링 LEGACY 프로젝트 복사

 

1. 복사 후 컨텍스트를 바꿔주기

 

2. 프로젝트의 의존성을 관리하는 pom.xml 

프로젝트명가 동일하게 정보 변경

 

3. 변경 후 Tomcat server의 server.xml을 다시 보면

context가 변경되어 있다. (바로 직접 변경해도 무관)


[JDBC]

Maven에 jdbc를 추가해줘야 한다.

 

 

< jdbc 설치관련 >

https://mvnrepository.com/tags/jdbc

 

MySQL과 Java를 연결해주는 connector

버전체크 필요

 

MySQL홈페이지에서 spring 프로젝트와 맞는 버전 재설치 필요 (ver 8.0.22)

 

 

다운그레이드 후 Connector 에  Maven 의존성 추가

https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.22

pom.xml에 의존성 추가

 

 

Back 단에서 사용하는 것들은 root-context.xml에 추가

 

 

Spring Boot에서는 jdbc의 Datasource Bean이 자동으로 생성되지만

 

Spring Framework에서는 Bean을  모두 직접 만들어줘야 한다.

 

DriverManagerDataSource의 setter역할을 한다.

 

 

** Spring JDBC (아직사용하지는 않지만 DataSoure Bean을 사용하기위해 설치)

Spring Framework와 버전이 맞아야함.

 

스프링 프레임워크와 버전 동일하게 pom.xml에 추가

 

< DB 재설치 후 >

ver2 database - member table 생성

mysql connector

/ JdbcRepository를 만들고,

@Repository
public class MemberJdbcRepository implements MemberRepository{

	private final DataSource dataSource;
	
	@Autowired
	public MemberJdbcRepository(DataSource dataSource) {
		System.out.println("[MemberJdbcRepository] 실행됨");
		this.dataSource = dataSource;
	}

	@Override
	public Member save(Member member) {
		return null;
	}

	@Override
	public Optional<Member> findById(Long id) {
		return null;
	}

	@Override
	public Optional<Member> findByName(String name) {
		return null;
	}

	@Override
	public List<Member> findAll() {
		return null;
	}
	
}

 

 

 

** 이미 연결된 설정이된 mysql DB가 있음에도  서버가 재실행 될 때마다 mysql-connector-java.jar 파일이 실행되며, 

중복해서 연결을 만드는 오류가 발생!

(=>구조적인 문제 : 따라서  프로젝트 내에서 계속 아닌 Tomcat에 옮겨 실행된느 위치를 지정해야 한다.)

 

서버 쪽에 옮기고 나서&nbsp; pom.xml에 의존성은 주석처리

 

 

 

/ JdbcRepository  - save()

 

주석별로 기능 설명 참고

@Override
public Member save(Member member) {
    String sql = "insert into member(name) values(?)"; // ?는 파라미터(? 1개 = 1번째)
    Connection con = null;
    PreparedStatement pstmt = null; // 동적 쿼리문에 필요
    ResultSet rs = null;

    // (DB)연결과 관련된 것은 모두 DataSource에 있다.
    // getConnection() 예외처리 필요
    try {
        con = dataSource.getConnection();
        pstmt = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
        // auto_increment(generated)인 'id' 준비

        pstmt.setString(1, member.getName());
        pstmt.executeUpdate(); // 값 변경이 아닌 DB에 요소 추가되는 Update 의미
        rs = pstmt.getGeneratedKeys();
        // return형 ResultSet에 관리되는 Row들 중 하나 객체반환 
        // (위에 코드에따라 실행되고, 마지막으로 자동 생성이된 Row하나 객체)

        // java는 DBMS처럼 table(column)개념이 없기 때문에 모든 컬럼 정보도 함께 (하나의 객체 형태로)넘어온다.
        if(rs.next()) { // 다음객체가 있다면 
            member.setId(rs.getLong(1)); // rs의 1번째 column(id)의 타입을 지정해서 값 세팅
        }

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        //** 이렇게 지정해준 이후 다시 할당된 값을 역순으로 해제해줘야 한다.
        try {
            if(rs != null) rs.close();
            if(pstmt != null) pstmt.close();
            if(con != null) con.close();
        }catch (Exception e2) { // 이 과정에서 또 예외처리 필요
            e2.printStackTrace();
        }
    }
    return member;
}

 

 

** Java App의 기준에서 DB와 데이터를 주고받는 작업은 I/O (Input / Output)가 발생하는데,

I/O가 발생하는 코드(ex) getConnection()등 )에는 예외가 발생하기 쉬워 무조건 예외처리가 되어있다.

 

cf) catch문의 .printStackTrace는 예외가 발생한곳에 스택트레이스가 출력되는 예외처리 메서드로 디버깅용,

실제 프로덕션 코드에서는 더 정교하고 적합한 예외처리가 필요하다.