1. 새 프로젝트 생성하고 pom.xml 수정하기

Spring Legacy Project Name : People
topLevelPackage : com.kopo.people

로 새 프로젝트를 만들고

pom.xml에 아래를 추가한다.

		<!-- SQLite -->
		<dependency>
			<groupId>org.xerial</groupId>
			<artifactId>sqlite-jdbc</artifactId>
			<version>3.27.2.1</version>
		</dependency>
		<!-- JSON -->
		<dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-mapper-asl</artifactId>
			<version>1.9.13</version>
		</dependency>

 

home.jsp에는 MVC 프로젝트 최초 생성시 자동으로 UTF-8 설정이 안 들어가니 기존에 있던걸 지우고 다음을 추가해준다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

 

2. DB 파일 가져오기

이클립스 내에서 가져오면 자동 refactor가 되고, 외부 파일에서 가져올 경우는 package 이름을 바꿔준다.

 

3. 새 객체 클래스를 만들어보자

우클릭 > Source > Generate Getters and Setters... 에서 게터 세터도 만들어주고

 

생성자도 만들어준다.

package com.kopo.people;

public class People {
	int idx;
	String name;
	String phone;
	String address;
	
	People() {
		
	}
	
	// public People(String name, String phone, String address)로 써도 되고, 접근 권한을 주고 싶은 만큼 바꾸는건 자유롭다.
	People(String name, String phone, String address) {
		this.name = name;
		this.phone = phone;
		this.address = address;
	}
	
	People(int idx, String name, String phone, String address) {
		this.idx = idx;
		this.name = name;
		this.phone = phone;
		this.address = address;
	}
	
	
	public int getIdx() {
		return idx;
	}
	public void setIdx(int idx) {
		this.idx = idx;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
}

 

4. 쿼리로 테이블을 생성해보자 (create)

기존의 DB.java를 그대로 이용할거다. DB.java는 수정 없이 객체 클래스와 컨트롤러만 수정해서 새로운 프로젝트를 진행한다.

HomeController

	// 쿼리를 이용해 테이블 생성하기.
	@RequestMapping(value = "/create", method = RequestMethod.GET)
	public String create(Locale locale, Model model) {
		DB db = new DB<People>(".../people.db", "people");
		
		if (db.open()) {
			if (db.createTable(new People())) {
				model.addAttribute("message", "테이블이 생성되었습니다.");
			} else {
				model.addAttribute("message", "테이블 생성에 실패하였습니다.");
			}
			db.close();
		} else {
			model.addAttribute("message", "DB파일을 사용할 수 없습니다.");
		}

		return "message";
	}

 

message.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Message</title>
  </head>
  <body>
    <P>${message}</P>
  </body>
</html>

 

 

5. 데이터를 입력해보자 (insert)

HomeController (페이지 response)

	// insert 페이지 response
	@RequestMapping(value = "/insert", method = RequestMethod.GET)
	public String insert(Locale locale, Model model) {
		return "insert";
	}

 

insert.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>입력 페이지</title>
  </head>
  <body>
    <form action="/people/insert_action" method="post">
      <input type="text" name="name" placeholder="이름을 입력하세요.">
      <input type="text" name="phone" placeholder="전화번호를 입력하세요.">
      <input type="text" name="address" placeholder="주소를 입력하세요.">
      <input type="submit" value="입력">
    </form>
  </body>
</html>

method를 홈컨트롤러와 같게 일치시키는 것에 주의하자. insert니까 POST를 사용하자.

 

HomeController (액션)

	// insert 액션
	@RequestMapping(value = "/insert_action", method = RequestMethod.POST)
	public String insertAction(Locale locale, Model model, HttpServletRequest request) {
		try {
			request.setCharacterEncoding("UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		// DB에 쿼리 전송 및 데이터 유효성 검사
		DB db = new DB<People>("/Users/saebyul/SqliteDB/0909people.db", "people");
		
		if (db.open()) {
			try {
				String name = request.getParameter("name");
				String phone = request.getParameter("phone");
				String address = request.getParameter("address");

				if (db.insertData(new People(name, phone, address))) {
					model.addAttribute("message", "새 데이터를 추가했습니다.");
				} else {
					model.addAttribute("message", "데이터 추가에 실패했습니다.");
				};
			} catch (Exception e) {
				e.printStackTrace();
				model.addAttribute("message", "데이터가 올바르지 않습니다.");
			}

			db.close();
		} else {
			model.addAttribute("message", "DB파일을 사용할 수 없습니다.");
		}
		
		return "redirect:/";
	}

redirect 사용법을 기억하자

 

6. 데이터를 조회해보자 (select)

기존

	// 데이터 객체를 읽어 String으로 return (데이터를 담을 때 단순 String을 사용)
	public String toHtmlString(ArrayList<People> objects) {
		String htmlText = "";
		for (People each : objects) {
			htmlText = htmlText + "<tr>";
			htmlText = htmlText + "<td>" + each.idx + "</td>";
			htmlText = htmlText + "<td>" + each.name + "</td>";
			htmlText = htmlText + "<td>" + each.phone + "</td>";
			htmlText = htmlText + "<td>" + each.address + "</td>";
			htmlText = htmlText + "</tr>";
		}
		return htmlText;
	}

 

새 방법 (StringBuffer) 스트링 버퍼를 이용해보자

	// 데이터 객체를 읽어 String으로 return (데이터를 담을 때 StringBuffer를 사용)
	public String toHtmlString(ArrayList<People> objects) {
		StringBuffer htmlString = new StringBuffer();
		for (People each : objects) {
			htmlString.append("<tr>");
			htmlString.append("<td>" + each.idx + "</td>");
			htmlString.append("<td>" + each.name + "</td>");
			htmlString.append("<td>" + each.phone + "</td>");
			htmlString.append("<td>" + each.address + "</td>");
			htmlString.append("</tr>");
		}
		return htmlString.toString();
	}

 

 

home.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
  <head>
  	<title>데이터 조회</title>
  </head>
  <body>
    <a href="/people/insert">데이터 입력하러 가기</a><br>
    <table style="width: 100%;">
      <thead>
        <tr>
          <th>idx</th>
          <th>이름</th>
          <th>전화번호</th>
          <th>주소</th>
        </tr>
      </thead>
      <tbody>
        ${htmlString}
      </tbody>
    </table>
  </body>
</html>

 

 

CSS를 안 해서 모양은 좀 그렇다...

 

 

 

이런식으로... 기존 DB 파일을 재활용 할 수 있다. 홈컨트롤러도 가져와서 조금만 수정해서 재활용 가능하고...

지금까지 위 코드를 정리하면

HomeController

package com.kopo.people;

import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		DB db = new DB<People>(".../people.db", "people");
		
		if (db.open()) {
			try {
				ArrayList<People> resultData = db.selectData(new People());
				model.addAttribute("htmlString", (new People()).toHtmlString(resultData));	// People()을 인스턴스화 해 새 객체로 만든다.
			} catch (Exception e) {
				e.printStackTrace();
				model.addAttribute("htmlString", "데이터를 조회를 할 수 없습니다.");
			}
			
			db.close();
		} else {
			model.addAttribute("htmlString", "DB파일을 사용할 수 없습니다.");
		}
		
		return "home";
	}
	
	// 쿼리를 이용해 테이블 생성하기.
	@RequestMapping(value = "/create", method = RequestMethod.GET)
	public String create(Locale locale, Model model) {
		DB db = new DB<People>(".../people.db", "people");
		
		if (db.open()) {
			if (db.createTable(new People())) {
				model.addAttribute("message", "테이블이 생성되었습니다.");
			} else {
				model.addAttribute("message", "테이블 생성에 실패하였습니다.");
			}
			db.close();
		} else {
			model.addAttribute("message", "DB파일을 사용할 수 없습니다.");
		}

		return "message";
	}
	
	// insert 페이지 response
	@RequestMapping(value = "/insert", method = RequestMethod.GET)
	public String insert(Locale locale, Model model) {
		return "insert";
	}
	
	// insert 액션
	@RequestMapping(value = "/insert_action", method = RequestMethod.POST)
	public String insertAction(Locale locale, Model model, HttpServletRequest request) {
		try {
			request.setCharacterEncoding("UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		// DB에 쿼리 전송 및 데이터 유효성 검사
		DB db = new DB<People>(".../people.db", "people");
		
		if (db.open()) {
			try {
				String name = request.getParameter("name");
				String phone = request.getParameter("phone");
				String address = request.getParameter("address");

				if (db.insertData(new People(name, phone, address))) {
					model.addAttribute("message", "새 데이터를 추가했습니다.");
				} else {
					model.addAttribute("message", "데이터 추가에 실패했습니다.");
				};
			} catch (Exception e) {
				e.printStackTrace();
				model.addAttribute("message", "데이터가 올바르지 않습니다.");
			}

			db.close();
		} else {
			model.addAttribute("message", "DB파일을 사용할 수 없습니다.");
		}
		
		return "redirect:/";
	}
}

 

DB

package com.kopo.people;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

import org.sqlite.SQLiteConfig;

public class DB<T> {
	private String dbFileName;
	private String tableName;
	private Connection connection;
	static {
		try {	// 이 이름을 가진 DB가 없을 수도 있기 때문에 try~catch
			Class.forName("org.sqlite.JDBC");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public DB (String dbFileName, String tableName) {
		this.dbFileName = dbFileName;
		this.tableName = tableName;
	}
	
	public boolean open() {
		SQLiteConfig config = new SQLiteConfig();
		try {
			this.connection = DriverManager.getConnection("jdbc:sqlite:/" + this.dbFileName, config.toProperties());
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	public void close() {
		if (this.connection != null) {
			try {
				this.connection.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
//	public void createTable() {
//		String query = "CREATE TABLE " + this.tableName + " (idx INT PRIMARY KEY, name TEXT, middleScore INT, finalScore INT)";
//		try {
//			Statement statement = this.connection.createStatement();
//			statement.executeUpdate(query);
//			statement.close();
//		} catch (SQLException e) {
//			e.printStackTrace();
//		}
//	}
	
	public void createTable() {
		String fieldString = "";
		fieldString = fieldString + "idx INT PRIMARY KEY";
		fieldString = fieldString + ", name TEXT";
		fieldString = fieldString + ", middleScore INT";
		fieldString = fieldString + ", finalScore INT";
		String query = "CREATE TABLE " + this.tableName + " (" + fieldString + ")";
		try {
			Statement statement = this.connection.createStatement();
			statement.executeUpdate(query);
			statement.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	// create table 쿼리 실행
	public boolean createTable(T t) {	// 기존에는 Student student라고 해서 Student라는 객체가 들어온다 명시를 했다. T는 어떤 객체가 들어올지 모른단 뜻. DB를 DB<T>로 Generic(제네릭)을 사용한다.
		Class<?> dataClass = t.getClass();	// t의 Class Object를 가져와 return해서 dataClass라는 변수명에 저장.
		Field[] dataClassFields = dataClass.getDeclaredFields();	// dataClass라는 클래스의 변수들을 array로 return.
		
		String fieldString = "";
		
		for (Field field: dataClassFields) {	//  array로부터 for each 문을 돌면서 하나씩 분해해 쿼리에 넣을 문자열을 만든다.
			if (!fieldString.isEmpty()) {
				fieldString = fieldString + ",";
			}
			String fieldName = field.getName();
			String fieldType = field.getType().toString();
			fieldString = fieldString + fieldName;
			if (fieldName.matches("idx")) {
				fieldString = fieldString + " INTEGER PRIMARY KEY AUTOINCREMENT";
			} else if (fieldType.matches("(int|long)")) {
				fieldString = fieldString + " INTEGER";
			} else if (fieldType.matches("(float|double)")) {
				fieldString = fieldString + " REAL";
			} else if (fieldType.matches(".*String")) {
				fieldString = fieldString + " TEXT";
			}
		}
		
		String query = "CREATE TABLE " + this.tableName + " (" + fieldString + ")";
		try {
			Statement statement = this.connection.createStatement();
			statement.executeUpdate(query);
			statement.close();
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	// insert 쿼리 실행
//	public boolean insertData(T t) {
//		Class<?> dataClass = t.getClass();
//		Field[] dataClassFields = dataClass.getDeclaredFields();
//		
//		String fieldString = "";
//		String valueString = "";
//		
//		for (Field field: dataClassFields) {
//			String fieldName = field.getName();
//			String fieldType = field.getType().toString();
//			if (fieldName.matches("idx")) {
//				continue;
//			}
//			if (!fieldString.isEmpty()) {
//				fieldString = fieldString + ",";
//			}
//			if (!valueString.isEmpty()) {
//				valueString = valueString + ",";
//			}
//			fieldString = fieldString + fieldName;
//			
//			// DB 컬럼에 넣을 값. 값이 문자열이면 ' ' 로 감싸주고, 그렇지 않으면 그냥 입력.
//			try {
//				if (fieldType.matches(".*String")) {	// 문자열이면 ' '로 감싸준다.
//					valueString = valueString + "'" + field.get(t) + "'";
//				} else {								// 아니면 그냥 넣는다.
//					valueString = valueString + field.get(t);
//				}
//			} catch (IllegalArgumentException e) {
//				e.printStackTrace();
//			} catch (IllegalAccessException e) {
//				e.printStackTrace();
//			}
//		}
//		
//		// 위에서 구한 fieldString(name, middleScore, finalScore...)와 valueString("홍길동", 100, 80)을 넣어 쿼리문을 만든다.
//		String query = "INSERT INTO " + this.tableName + " (" + fieldString + ") VALUES(" + valueString + ")";
//		try {
//			Statement statement = this.connection.createStatement();
//			statement.executeUpdate(query);
//			statement.close();
//			return true;
//		} catch (SQLException e) {
//			e.printStackTrace();
//		}
//		return false;
//	}
	
	// insert 쿼리 실행 (Inner Class를 활용한 preparedStatement)
	public boolean insertData(T t) {
		Class<?> dataClass = t.getClass();	// Student.java
		Field[] dataClassFields = dataClass.getDeclaredFields();	// Student.java의 내용을 읽는다.
		
		String fieldString = "";	// 변수명을 저장 (name, middleScore, finalScore)...
		String valueString = "";	// 변수값을 저장 ("홍길동", 100, 80)...
		
		// Inner Class 만들기
		class PreparedValue {
			int type = 0;
			int intValue = 0;
			double floatValue = 0;
			String stringValue = "";
			
			PreparedValue(int intValue) {
				this.type = 1;
				this.intValue = intValue;
			}
			
			PreparedValue(double floatValue) {
				this.type = 2;
				this.floatValue = floatValue;
			}
			
			PreparedValue(String stringValue) {
				this.type = 3;
				this.stringValue = stringValue;
			}
		}
		
		// 값을 저장할 배열을 변수로 선언
		ArrayList<PreparedValue> preparedValue = new ArrayList<PreparedValue>();
		
		// for each를 이용해 
		for (Field field: dataClassFields) {	// Student.java의 내용을 한 줄씩 읽는다.
			// Step 1. 각 라인을 each로 읽어온다.
			String fieldName = field.getName();	// dataClassFields에서 각각 field(each)로 읽어온다... name, middleScore, finalScore
			String fieldType = field.getType().toString();	// 위와 마찬가지로 field(each)로 읽어온다... String, int, int
			
			if (fieldName.matches("idx")) {	// idx는 insert때는 auto increment로 필요가 없으니 넘어간다. 
				continue;
			}
			
			
			// Step 2. fieldString 만들기
			if (!fieldString.isEmpty()) {	// 최초 인입 이후 두 번째 for문 돌 때 콤마를 추가해준다. (name, middleScore, finalScore)...
				fieldString = fieldString + ",";	// fieldString 자기 자신에게 ","를 하나씩 추가해준다.
			}
			fieldString = fieldString + fieldName;	// 최초 인입 for문부터 fieldString 자기 자신에게 fieldName(name, middleScore, finalScore)를 하나씩 추가해준다.
			
			
			// Step 3. valueString 만들기
			if (!valueString.isEmpty()) {	// 최초 인입 이후 두 번째 for문 돌 때 콤마를 추가해준다. ("홍길동", 100, 80)...
				valueString = valueString + ",";	// 더한 결과는 값1, 값2, 값3... 의 형태가 된다.
			}
			// 최초 인입 for문부터 preparedValue라는 ArrayList에 데이터 타입과 값을 담고,
			// valueString 자기 자신에게는 그냥 아무 의미 없는 나중에 preparedStatement에 값을 넣기 위해 개수만 맞 ?, ?, ?를 하나씩 추가해준다.
			try {
				// preparedValue라는 ArrayList에 데이터 타입과 값을 담는다. (preparedStatement.setString(1, name);, preparedStatement.setInt(2, middleScore); 이 부분에 해당하는 값과 데이터 타입을 담는다.)
				if (fieldType.matches("(int|long|short)")) {
					preparedValue.add(new PreparedValue(field.getInt(t)));
				} else if (fieldType.matches("(float|double)")) {
					preparedValue.add(new PreparedValue(field.getDouble(t)));
				} else if (fieldType.matches(".*String")) {
					preparedValue.add(new PreparedValue(field.get(t).toString()));
				}
				valueString = valueString + "?";	// 기존의 String query = "INSERT INTO " + this.dbTableName + " (name, middleScore, finalScore) VALUES (?, ?, ?);"; 에서 ??? 이걸 넣어주기 위한 로직.
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		
		// 위에서 구한 fieldString(name, middleScore, finalScore...)와 valueString("홍길동", 100, 80)을 넣어 쿼리문을 만든다.
		String query = "INSERT INTO " + this.tableName + " (" + fieldString + ") VALUES(" + valueString + ")";
		try {
			PreparedStatement preparedStatement = this.connection.prepareStatement(query);	// 쿼리문을 컴파일
			
			// preparedValue라는 변수명을 가진 ArrayList에는 각각의 값이 객체로 들어가있다. << due to : preparedValue.add(new PreparedValue(field.getInt(t))) >>
			// 이 객체를 하나씩 꺼내와 이너클래스의 타입을 이용해 int면 setInt로 i + 1 번째에 preparedValue로부터 get 한 값을 넣는다.
			for (int i = 0; i < preparedValue.size(); i++) {
				if (preparedValue.get(i).type == 1) {
					preparedStatement.setInt(i + 1, preparedValue.get(i).intValue);
				} else if (preparedValue.get(i).type == 2) {
					preparedStatement.setDouble(i + 1, preparedValue.get(i).floatValue);
				} else if (preparedValue.get(i).type == 3) {
					preparedStatement.setString(i + 1, preparedValue.get(i).stringValue);
				}
			}
			preparedStatement.executeUpdate();
			preparedStatement.close();
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	// update 쿼리를 만들자
	// Step 1. update 쿼리 실행
//	public void updateData(int idx, String memo) {
//		String query = "UPDATE" + this.tableName + " SET memo='" + memo + "' WHERE idx=" + idx;
//		try {
//			Statement statement = this.connection.createStatement();
//			statement.executeUpdate(query);
//			statement.close();
//		} catch (SQLException e) {
//			e.printStackTrace();
//		}
//	}
	
	// Step 2. update 쿼리 실행
//	public void updateData(int idx, String memo) {
//		String setString = "memo='" + memo + "'";
//		String whereString = "idx=" + idx;
//		String query = "UPDATE" + this.tableName + " SET " + setString + " WHERE " + whereString;
//		try {
//			Statement statement = this.connection.createStatement();
//			statement.executeUpdate(query);
//			statement.close();
//		} catch (SQLException e) {
//			e.printStackTrace();
//		}
//	}
	
	// Step 3. update 쿼리 실행
//	public boolean updateData(T t) {
//		Class<?> dataClass = t.getClass();
//		Field[] dataClassFields = dataClass.getDeclaredFields();
//		String setString = "";
//		String whereString = "";
//		for (Field field : dataClassFields) {
//			if (!setString.isEmpty()) {
//				setString = setString + ",";
//			}
//			String fieldName = field.getName();
//			String fieldType = field.getType().toString();
//			try {
//				if (fieldName.matches("idx")) {
//					whereString = "idx=" + field.get(t);
//				} else if (fieldType.matches(".*String")) {
//					setString = setString + fieldName + "=" + "'" + field.get(t) + "'";
//				} else {
//					setString = setString + fieldName + "=" + field.get(t);
//				}
//			} catch (IllegalArgumentException e) {
//				e.printStackTrace();
//			} catch (IllegalAccessException e) {
//				e.printStackTrace();
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
//		}
//
//		String query = "UPDATE " + this.tableName + " SET " + setString + " WHERE " + whereString;
//		try {
//			Statement statement = this.connection.createStatement();
//			statement.executeUpdate(query);
//			statement.close();
//			return true;
//		} catch (SQLException e) {
//			e.printStackTrace();
//		}
//		return false;
//	}
	
	// Step final.
	// update 쿼리 실행 (Inner Class를 활용한 preparedStatement)
	public boolean updateData(T t) {
		Class<?> dataClass = t.getClass();
		Field[] dataClassFields = dataClass.getDeclaredFields();
		
		String whereString = "";	// where 조건을 저장 idx=7
		String valueString = "";	// 변수값을 저장 ("홍길동", 100, 80)...
		
		// Inner Class 만들기		
		class PreparedValue {
			boolean isString;
			Object value;
			
			PreparedValue(boolean isString, Object value) {
				this.isString = isString;
				this.value = value;				
			}
		}

		ArrayList<PreparedValue> preparedValue = new ArrayList<PreparedValue>();
		
		// for each를 이용해 
		for (Field field : dataClassFields) {
			// Step 1. 각 라인을 each로 읽어온다.
			String fieldName = field.getName();
			String fieldType = field.getType().toString();
			
			// Step 2. valueString 만들기 (insert에서는 이 과정을 Step 3.에서 했었다.)
			if (!valueString.isEmpty()) {
				valueString = valueString + ",";
			}
			
			try {
				// idx는 value와 구분한다. idx일 때는 valueString = valueString + fieldName + "=?"; 는 실행이 되면 안 되므로 continue;
				if (fieldName.matches("idx")) {
					whereString = "idx=" + field.get(t);
					continue;
				}
				
				if (fieldType.matches(".*String")) {
					preparedValue.add(new PreparedValue(true, field.get(t)));
				} else {
					preparedValue.add(new PreparedValue(false, field.get(t)));
				}
				valueString = valueString + fieldName + "=?";	// 기존의 String query = "UPDATE " + this.dbTableName + " SET name=?, middleScore=?, finalScore=? WHERE idx=?;";
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		String query = "UPDATE " + this.tableName + " SET " + valueString + " WHERE " + whereString;
		try {
			PreparedStatement preparedStatement = this.connection.prepareStatement(query);	// 쿼리문을 컴파일
			
			for (int i = 0; i < preparedValue.size(); i++) {
				if (preparedValue.get(i).isString) {
					preparedStatement.setObject(i + 1, preparedValue.get(i).value.toString());
				} else {
					preparedStatement.setObject(i + 1, preparedValue.get(i).value);
				}
			}
			
			preparedStatement.executeUpdate();
			preparedStatement.close();
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	// select 쿼리를 만들자
	// Step 1. select 쿼리 실행
//	public String selectData() {
//		String query = "SELECT * FROM " + this.tableName;
//		String htmlText = "";
//		
//		try {
//			Statement statement = this.connection.createStatement();
//			ResultSet result = statement.executeQuery(query);
//			while(result.next()) {
//				htmlText = htmlText + "<tr>";
//				htmlText = htmlText + "<td>" + result.getInt("idx") + "</td>";
//				htmlText = htmlText + "<td>" + result.getString("name") + "</td>";
//				htmlText = htmlText + "<td>" + result.getInt("middleScore") + "</td>";
//				htmlText = htmlText + "<td>" + result.getInt("finalScore") + "</td>";
//				htmlText = htmlText + "</tr>";
//			}
//			result.close();
//			statement.close();
//		} catch (SQLException e) {
//			e.printStackTrace();
//		}
//		return htmlText;
// 	}
	
	// Step 2. select 쿼리 실행
//	public String selectData(T t) {
//		String query = "SELECT * FROM " + this.tableName;
//		ArrayList<Student> resultDataSet = new ArrayList<Student>();
//		
//		try {
//			Statement statement = this.connection.createStatement();
//			ResultSet result = statement.executeQuery(query);
//			while(result.next()) {	// Field를 알아야지 가져올 수 있다.
//				resultDataSet.add(new Student(result.getInt("idx"),
//											  result.getString("name"),
//											  result.getInt("middleScore"),
//											  result.getInt("finalScore")));
//			}
//			result.close();
//			statement.close();
//		} catch (SQLException e) {
//			e.printStackTrace();
//		}
//		String htmlText = (new Student()).toThmlString(resultDataSet);
//		return htmlText;		
// 	}
	
	// Step 3. select 쿼리 실행
	public ArrayList<T> selectData(T t) {
		Class<?> dataClass = t.getClass();
		Field[] dataClassFields = dataClass.getDeclaredFields();
		
		String query = "SELECT * FROM " + this.tableName;
		ArrayList<T> resultDataSet = new ArrayList<T>();
				
		try {
			Statement statement = this.connection.createStatement();
			ResultSet result = statement.executeQuery(query);
			while(result.next()) {
				T rowData = (T)dataClass.getDeclaredConstructor().newInstance();	// unknown 클래스를 가지고 객체를 생성하는 방법.
				
				// for each를 이용해 
				for (Field field: dataClassFields) {	// Student.java의 내용을 한 줄씩 읽는다.
					// Step 1. 각 라인을 each로 읽어온다.
					String fieldName = field.getName();	// dataClassFields에서 각각 field(each)로 읽어온다... name, middleScore, finalScore
					String fieldType = field.getType().toString();	// 위와 마찬가지로 field(each)로 읽어온다... String, int, int
						
					if (fieldType.matches("(int|short)")) {
						field.setInt(rowData, result.getInt(fieldName));
					} else if (fieldType.matches("(long)")) {
						field.setLong(rowData, result.getLong(fieldName));
					} else if (fieldType.matches("(float|double)")) {
						field.setDouble(rowData, result.getDouble(fieldName));
					} else if (fieldType.matches(".*String")) {
						field.set(rowData, result.getString(fieldName));
					}
				}
				resultDataSet.add(rowData);
			}
			result.close();
			statement.close();
			
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return resultDataSet;		
 	}
	
	
	
	
	
	
	// String이 정수로 형변환이 가능한지 아닌지를 검사하는 메소드
	public static boolean isIntegerString(String numericString) {
		try {
			int result = Integer.parseInt(numericString);
			return true;
		} catch (Exception e) {
			
		}
		return false;
	}
	
	// String이 실수로 형변환이 가능한지 아닌지를 검사하는 메소드
	public static boolean isFloatString(String numericString) {
		try {
			double result = Double.parseDouble(numericString);
			return true;
		} catch (Exception e) {
			
		}
		return false;
	}

	
	
//	
//	class PreparedValue {
//		int type = 0;
//		
//	}
//	
//	ArrayList<PreparedValue> preparedValue = new ArrayList<PreparedValue>();
//	
//	for (Field field: dataClassFields) {
//		
//	}
	

}

 

People.java

package com.kopo.people;

import java.util.ArrayList;

public class People {
	int idx;
	String name;
	String phone;
	String address;
	
	People() {
		
	}
	
	// public People(String name, String phone, String address)로 써도 되고, 접근 권한을 주고 싶은 만큼 바꾸는건 자유롭다.
	People(String name, String phone, String address) {
		this.name = name;
		this.phone = phone;
		this.address = address;
	}
	
	People(int idx, String name, String phone, String address) {
		this.idx = idx;
		this.name = name;
		this.phone = phone;
		this.address = address;
	}
	
	// 데이터 객체를 읽어 String으로 return (데이터를 담을 때 단순 String을 사용)
//	public String toHtmlString(ArrayList<People> objects) {
//		String htmlText = "";
//		for (People each : objects) {
//			htmlText = htmlText + "<tr>";
//			htmlText = htmlText + "<td>" + each.idx + "</td>";
//			htmlText = htmlText + "<td>" + each.name + "</td>";
//			htmlText = htmlText + "<td>" + each.phone + "</td>";
//			htmlText = htmlText + "<td>" + each.address + "</td>";
//			htmlText = htmlText + "</tr>";
//		}
//		return htmlText;
//	}
	
	// 데이터 객체를 읽어 String으로 return (데이터를 담을 때 StringBuffer를 사용)
	public String toHtmlString(ArrayList<People> objects) {
		StringBuffer htmlString = new StringBuffer();
		for (People each : objects) {
			htmlString.append("<tr>");
			htmlString.append("<td>" + each.idx + "</td>");
			htmlString.append("<td>" + each.name + "</td>");
			htmlString.append("<td>" + each.phone + "</td>");
			htmlString.append("<td>" + each.address + "</td>");
			htmlString.append("</tr>");
		}
		return htmlString.toString();
	}
	
	
	public int getIdx() {
		return idx;
	}
	public void setIdx(int idx) {
		this.idx = idx;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
}

 

message.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Message</title>
  </head>
  <body>
    <P>${message}</P>
  </body>
</html>

 

home.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
  <head>
  	<title>데이터 조회</title>
  </head>
  <body>
    <a href="/people/insert">데이터 입력하러 가기</a><br>
    <table style="width: 100%;">
      <thead>
        <tr>
          <th>idx</th>
          <th>이름</th>
          <th>전화번호</th>
          <th>주소</th>
        </tr>
      </thead>
      <tbody>
        ${htmlString}
      </tbody>
    </table>
  </body>
</html>

 

insert.jps

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>입력 페이지</title>
  </head>
  <body>
    <form action="/people/insert_action" method="post">
      <input type="text" name="name" placeholder="이름을 입력하세요.">
      <input type="text" name="phone" placeholder="전화번호를 입력하세요.">
      <input type="text" name="address" placeholder="주소를 입력하세요.">
      <input type="submit" value="입력">
    </form>
  </body>
</html>

 

 

 

 

 

 

이것들을 더욱 발전시키려면

더보기

DB : 1. 이름, 전화번호, 주소만 했지만 실제로는 생성일, 수정일도 만들어야한다.

2. 지금처럼 property를 직접 읽어오는 것 외에 getter, setter를 이용하는 것을 만들 수 있다. 그리고 더 발전시키면 getter, setter가 있다면 그것을 사용, 없다면 property를 사용하도록 더 업그레이드 시킬 수 있다.

3. ajax를 사용해서 작업할 경우는 이런 작업들을 자바 서버가 아닌 클라이언트의 자바 스크립트에서 하기 때문에 이런 것들이 필요가 없다. 그런 것도 고려를 해야한다.

HomeController : 이것 역시 DB처럼 반응형으로 만들어서 사용할 수도 있다고 한다... 어떻게 해야할까?

 

이런 백단의 공통 코드들을 발전시키고, 다양한 버전을 만들어 가지고 있는 것이 내 기술이 된다. 이런것들이 모이면 객체만 만들어 그러면 다 돌아가게 해줄게 하는 정부 전자프레임워크같은 나만의 프레임워크가 되는 것이다.

 

그리고 객체 파일도 내가 만든 프로젝트고 파일이기 때문에 생성자를 생성하는 방식으로 진행했지만 현업에 나가면 생성자를 생성하는 방식도 많지만 getter, setter를 이용하는 경우도 많으니 꼭 알아야 한다.

 

현업에서는 DB파일을 불러올 경우 매번 패키지 이름을 수정하기보다는

방법 1 ) scr/main/java에 com.kopo.people이라는 기본 패키지 외에 새로 패키지 생성을 해서 com.kopo.commom 이런식으로 공통 패키지를 만들고, 수정하지 않을 파일은 공통 패키지 commom에 보내고, 수정할 파일은 현재 프로젝트 패키지 안에 넣는다.

그러면 com.kopo.people 패키지에 있는 HomeController는 DB 클래스 파일이 다른 패키지에 있으니 

import com.kopo.common.DB;

이런식으로 임포트를 해서 쓰게 된다. 그리고 이것이 일반적인 방법이다. (DB파일을 드래그 해서 가져오지 않고 패키지 파일을 드래그 해서 가져온다.)

 

방법 2 ) 아예 이 파일들을 다른 프로젝트로 보내고, 이 파일들을 연결해서 쓰는 방식을 이용한다. (이게 adaptor인가?)

방법 3 ) 아예 이런 패키지를 JAR 라이브러리 파일로 만들어서 넣는다.

+ Recent posts