공부/그룹 스터디

[3회차 05] DB table에 값 넣기, 수동 bean 등록

junani0v0 2024. 4. 18. 00:33

jsp -> controller -> service -> dao -> DB

 

이전까지 jsp와 controller만 사용했는데요 이제 DB table에 값을 넣어주기 위해 먼저 service 패키지를com.portfolio.www.service를 만들고 JoinService.java파일을 안에 만들겠습니다

public class JoinService {
public int join(HashMap<String, String> params) {

	return 0;
}

 

Bean 등록 방법

  • 어노테이션으로 자동 등록
  • 수동 등록

주로 비지니스 로직은 자동으로 할 수 있지만, 설정파일은 bean을 수동으로 등록해줘야합니다

 

 

< 수동 bean 등록 >

web.xml로 가서 <display-name>아래에 아래코드를 추가해줍니다.

<!-- Spring configuration start -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- 루트 어플리케이션컨텍스트 영역 -->
<!-- 시작점을 의미 한다 -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:/context*.xml</param-value>
</context-param>
<!-- Spring configuration end -->

web.xml은 프로젝트가 실행되면 다 읽어오는 역활을 합니다

여기서 listener는 거기 있는걸 읽어온다는 말입니다

뭘 읽어오나?

classpath에 있는 context*.xml (클래스패스는 빌드패스랑 똑같다)

java파일이 아니기에 src/main/resources에 context000.xml 형태로 넣는다

 

그러면 src/main/resources 에 context000.xml 을 만들어봅시다

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

</beans>

위 코드로 context-root.xml 파일을 만들었습니다

이제 여기에 JoinService의 bean을 수동으로 등록해 보겠습니다

 

빈을 등록하기 위해서는 bean을 관리하는 애는 네임스페이스가 beans입니다

beans안에 bean을 아래형식으로 만들어 줍니다

<bean id="" class=""/>

이게 bean의 기본문법으로 id와 class가 들어갑니다

  • id : bean을 생성을하면 그 값을 가져오기 위한 변수
  • class : 위치 즉, 어느 클래스를 bean으로 만들건지
<bean id="joinService" class="com.portfolio.www.service.JoinService">

그러면 우리는 변수 joinService에 JoinService의 위치를 class에 넣어줍니다

 

저장하고 서버를 실행해보면 콘솔에 우리가 넣은 id가 있는지 검색해봅니다

그러면 이렇게 joinService의 bean이 생성되었다고 나오면 수동 bean등록이 성공한겁니다

 

Tip.

자동으로 생성하는 친구(자동 bean 설정)는 다른 bean 받을 때 자동으로만 넣을 수 있습니다 (수동 넣을 수 X)

수동은 다른 bean을 수동 & 자동 둘다 받을 수 있습니다

 

LoginController에 우리가 만든 JoinService를 받으려면 @Autowired를 사용합니다

@Controller
public class LoginController {
	
	
	@RequestMapping("/loginPage.do")
	public String loginPage() {
		return "login";
	}
	
	@Autowired
	private JoinService joinService;
    
    @RequestMapping("/join.do")
    public String join(@RequestParam HashMap<String, String> params) {
    joinService.join(params);
    return "login";
    }
}
public int join(HashMap<String, String> params) {
    System.out.println(params);
    return 0;
}

LoginController에 @Autowired를 추가하고 join메스드에서 params값을 JoinService로 보내는 코드를 작성해고 JoinService에 params값이 잘나오는지 출력해봅니다

{memberId=admin, email=aaa@aaa.com, passwd=1234}

params값이 넘어오는걸 확인했으면 이제 DB를 불러와야하니 설정을 추가해 주겠습니다

 

< DB설정 >

datasource를 등록해 보겠습니다

먼저 src/main/java에 context-datasource.xml을 만들어줍니다

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

	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost:53306/forum?serverTimezone=Aisa/Seoul" />
		<property name="username" value="root"/>
		<property name="password" value="admin_123"/>
	</bean>

</beans>

이것도 context000.xml형식에 bean에 id와 class가 선언되어있어 빈을 수동으로 생성합니다

<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />

이건 DB엔진마다 조금씩 다릅니다

<property name="url" value="jdbc:mysql://localhost:53306/forum" />

jdbc:mysql://localhost:{DB에 설정한 Port}/{DB이름} 을 값으로 넣습니다

그다음 아이디와 비밀번호를 넣어줍니다

서버를 돌려보면 dataSource의 bean이 잘 생성된걸 확인할 수 있습니다

 

그다음은 com.portfolio.www.dao 패키지를 만들고 JoinDao.java 파일은 만들어보겠습니다

public class JoinDao extends JdbcTemplate{

	public int join(HashMap<String, String> params) {
		String sql = "";

		return 0;
	}
}

회원가입시 필요한 값을 HashMap으로 받고 나중에 sql을 추가해야되서 선언을 해놓고 return을 0으로 일단 작성하였습니다

<bean id ="joinDao" class="com.portfolio.www.dao.JoinDao"/>

JoinDao의 bean도 context-root.xml에 가서 수동으로 등록해줍니다

 

이제 의존관계를 봐봐야하는데 dao를 쿼리를 실행하고 하는데 실행을 할 수 있는 datasource를 만들었는데

우리는 DB를 datasource를 통해서만 접근을 할것입니다.

하지만 dao는 datasource를 가지고있어야 접근이 가능한데 bean을 등록하고 JoinDao클래스를 만들었는데 datasource를 넘겨줘야합니다(그래야 변수를 가질 수 있으니)

JoinDao를 상속받은 JdbcTemplate을 ctrl을 눌러 가보면 아래와 같은 형식으로 작성되어 있습니다

JdbcTemplate기본생성자가 나오고 그다음 생성자가 나오며 생성자에 datasource를 필수로 넣어줘야합니다

 

일단 JoinDao는 datasource를 받아와서 datasource를 넘겨줘야 함으로 아래처럼 작성을 합니다

public class JoinDao extends JdbcTemplate{
	
	public JoinDao() {}	//기본생성자
	public JoinDao(DataSource dataSource) { //데이터소스받는 생성자
		super(dataSource);
	}
	public int join(HashMap<String, String> params) {
		String sql = "";

		return 0;
	}
}

기본생서자와 데이터소스를 받는 생성자 하나를 작성해줍니다

 

< bean에 옵션 추가 >

이제 context-root.xml의 bean에 옵션?을 추가해 보겠습니다

constructor-arg (arg=argument) : bean이 생성될때 생성자에 아규먼트를 넘긴다

근데 어디 파라미터에 넣어야하는지 모름(파라미터는 순서알지만 아규먼트는 모름)

   ※ 파라미터 : 정의하는 곳 ex) (x,y)

   ※ 아규먼트 : 변수를 넘겨주는 곳 ex) (3,5)

constructor-arg 속성 4가지

  • index : 아규먼트를 어디 파라미터로 넣을지 위치
  • name
  • value : 넘겨주는 값이 기본형일때 사용
  • ref : 넘겨주는게 객체형이면 사용
    <bean id ="joinDao" class="com.portfolio.www.dao.JoinDao">
        <constructor-arg ref="dataSource"/>
    </bean>

우리는 생성자 파라마티 하나이기에 index생략가능

넘겨줄 값 datasource라는 bean을 이미 만들어 놓았기에 ref를 사용

ref에는 넣어줄 bean의 id를 넣어줍니다

즉, JoinDao가 bean으로 생성될때 생성자가 실행되어 아규먼트가 dataSource를 JoinDao에 넘기고 super를 통해 상위 클래스의 생성자를 한번더 호출

 

실제로 dataSource가 들어오는지 찍어봅시다

public class JoinDao extends JdbcTemplate{
	
	public JoinDao() {}	//기본생성자
	public JoinDao(DataSource dataSource) { //데이터소스받는 생성자
		super(dataSource);
		System.out.println("-----------------------"+dataSource);	//주소값 나오나 확인
	}

실제로 들어로면 이 dataSource의 주소값이 나옵니다

 

이제 다음으로 다른방법으로 Service와 Dao를 연결해보겠습니다

먼저 context-root.xml에 bean 옵션?을 추가하겠습니다

 

    <bean id="joinService" class="com.portfolio.www.service.JoinService">
        <property name="joinDao" ref="joinDao"/>
    </bean>

 

public class JoinService {
	
	private JoinDao joinDao;
	public void setJoinDao(JoinDao joinDao) {
		System.out.println("--------------" + joinDao +"  in joinService");
		this.joinDao = joinDao;
	}

 

property 속성 3가지

  • name : ex) private JoinDao joinDao 에서  joinDao가 name입니다
  • value : 넘겨주는 값이 기본형일때 사용
  • ref : 넘겨주는게 객체형이면 사용

ref에 변수명을 적으면 setJoinDao를 뒤집니다. 왜그럴까요??

 

바로 joinDao변수명이 들어가면 기본적으로 캡슐화(무조건 setter/getter사용)가 되어있기에 자동으로 변수명에 맞는 setter를 찾기 때문입니다

 

그다음 Service와 Dao가 연결이 잘되었는지 joinDao를 프린트해봐서 위처럼 나오면 성공입니다

 

이렇게하면 Controller - Service - Dao 가 모두 연결이 되었습니다 (예전 2점대 버전에서는 이렇게 했다는데 힘드네요...)

단점 : xml로 다 설정을 해줘야됨

장점 : 설정을 다 해주니 오류 찾기 쉬움

 

< insert 쿼리 작성 >

이제 JoinDao의 Insert 쿼리를 완성해 볼까요~

 

Dbeaver를 열고 입력해야하는 테이블을 우클릭 -> SQL생성 클릭 -> insert선택 -> Copy -> JoinDao sql에 붙여넣기

 

public int join(HashMap<String, String> params) {
    String sql = "INSERT INTO forum.`member`\r\n"
            + "(member_seq, member_id, passwd, member_nm, email, auth_yn, pwd_chng_dtm, join_dtm)\r\n"
            + "VALUES(0, '', '', '', '', '', '', '');";
    return 0; 
}

쿼리문 뒤에 \n,\r 다 삭제해줘야합니다 (안지우면 에러발생)

줄마다 끝에 "앞에 한칸씩 띄어쓰기해주세요(안전하기 위해)

member_seq 는 값을 넣어주는게 아니고 자동으로 올라가니 값 0과 함께 삭제

public int join(HashMap<String, String> params) {
    String sql = "INSERT INTO forum.`member` "
            + "( member_id, passwd, member_nm, email, auth_yn, pwd_chng_dtm, join_dtm) "
            + "VALUES( '', '', '', '', '', '', ''); ";
    return 0; 
}

이제 값을 넣어 줄것이기에 값의 ' '사이에 enter해서 줄바꿈해서 하나씩 입력

params.get("가져올값 이름")

public int join(HashMap<String, String> params) {
    String sql = "INSERT INTO forum.`member` "
            + "(member_id, passwd, member_nm, email, auth_yn, pwd_chng_dtm, join_dtm) "
            + "VALUES('"+ params.get("memberId")
            + "', '" + params.get("passwd")
            + "', '', '" + params.get("email")
            + "', '', '', '') ";
    return 0;

그다음 연월일 시분초를 넣어주겠습니다

public int join(HashMap<String, String> params) {
    String sql = "INSERT INTO forum.`member` "
            + "(member_id, passwd, member_nm, email, auth_yn, pwd_chng_dtm, join_dtm) "
            + "VALUES('"+ params.get("memberId")
            + "', '" + params.get("passwd")
            + "', '', '" + params.get("email")
            + "', '', '',  DATE_FORMAT(NOW()  ,'%Y%m%d%H%i%s')) ";
    return 0;

join_dtm의 값으로 DATE_FORMAT(NOW()  ,'%Y%m%d%H%i%s')를 넣어주며 ''로 감쌀 필요는 없습니다

<property name="url" value="jdbc:mysql://localhost:53306/forum?serverTimezone=Aisa/Seoul" />

그리고 context-datasource.xml에도 시간을 맞춰주겠습니다.

이렇게하면 이프로그램은 데이터소스를 아시아/서울 시간으로 설정하게 됩니다(서버 타입존과 상관 없이)

 

Tip.

SQL문은 대문자로 작성

 

public int join(HashMap<String, String> params) {
    String sql = "INSERT INTO forum.`member` "
            + "(member_id, passwd, member_nm, email, auth_yn, pwd_chng_dtm, join_dtm) "
            + "VALUES('"+ params.get("memberId")
            + "', '" + params.get("passwd")
            + "', '', '" + params.get("email")
            + "', '', '', DATE_FORMAT(NOW()  ,'%Y%m%d%H%i%s')) ";
    //sql실행 해줘야됨
    return update(sql); //이 메서드는 jdbc탭플릿에 있음
    //udate실행하면 왜 int 반환되냐?
    //select외 delete,update,insert는 로우가 늘어나거나 줄거나하면 영향을 받는다
    //그래서 영향을 받은 로우가 몇개인지 알려주기위해 int반환
}

JoinDao.java

public int join(HashMap<String, String> params) {
	return joinDao.join(params);
}

JoinService.java

JoinService join을 호출하기위해 코드추가 이렇게하면 이제 Controller에서 처리할 수 있습니다

	@RequestMapping("/join.do")
	public ModelAndView join(@RequestParam HashMap<String, String> params) {
		int result = joinService.join(params);
		ModelAndView mv = new ModelAndView();
		mv.addObject("result", result);
		mv.setViewName("login");
		return mv;
	}

그다음 LoginController의 join.do를 String에서 ModelAndView로 바꾸겠습니다

joinService를 가져오면 result가 나옵니다

ModelAndView를 선언해주고 addObject에 result를 넣어주고 setViewName을 login으로 해주고 return은 mv로 해줍니다

 

	@RequestMapping("/join.do")
	public ModelAndView join(@RequestParam HashMap<String, String> params) {
		int result = joinService.join(params);
		ModelAndView mv = new ModelAndView();
		mv.addObject("result", result);
		//결과값이 1이면 "회원가입이 되었습니다" 아니녀 "실패"
		String msg;
		if (result == 1) {
			msg = "회원가입이 되었습니다";
		}else {
			msg = "실패";
		}
		mv.addObject("msg", msg);
		mv.setViewName("login");
		return mv;
	}

그다음 result가 1이면 "회원가입이 되었습니다" 아니면 "실패" 라는 메시지가 나오게 추가해 보겠습니다

 

<script type="text/javascript">
    	window.onload = function() {
    		var result = '${result}';
        	var msg = '${msg}';
        	
        	if (result != '') {
        		alert(result)
        	}
    	};
</script>

그리고 메시지를 출력하기위해 login.jsp에 기능을 추가해줍니다

 

 

Tip.

"Property"는 객체의 특징을 나타내는 변수(객체의 속성을 가리킴)

"Attribute"는 주로 HTML요소의 특성을 나타냄(ex.HTML요소의 속성[attribute]는 해당 요소의 특징을 지정합니다)

 

"Parmeter"는 함수 정의에 포함된 변수 (함수가 정의될 때, 파라미터는 함수에 전달될 값의 이름)

"Argument"는 함수 호출 시 실제로 전달되는 (함수를 호출할때, 인자는 함수에 전달되는 실제 값)

 

즉, property = parameter / attribute = argument 라고 보면됩니다