1. 정리 1의 Create에 DB 생성과 실패에 따른 결과를 받아 테이블 생성/실패 처리 추가하기
HomeController
// 쿼리를 이용해 테이블 생성하기.
@RequestMapping(value = "/create", method = RequestMethod.GET)
public String create(Locale locale, Model model) {
DB db = new DB<Student>(".../student.db", "student");
// DB db = new DB<Color>(".../color.db", "color");
// DB db = new DB<Color>(".../memo.db", "memo");
if (db.open()) {
if (db.createTable(new Student())) {
// if (db.createTable(new Color())) {
// if (db.createTable(new Memo())) {
model.addAttribute("message", "테이블이 생성되었습니다.");
} else {
model.addAttribute("message", "테이블 생성에 실패하였습니다.");
}
db.close();
} else {
model.addAttribute("message", "DB파일을 사용할 수 없습니다.");
}
return "message";
}
DB
// 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;
}
2. 이번에는 Insert를 만들자.
HomeController
// 데이터 입력하기.
@RequestMapping(value = "/insert", method = RequestMethod.GET)
public String insert(Locale locale, Model model,
@RequestParam("name") String name,
@RequestParam("middleScore") int middleScore,
@RequestParam("finalScore") int finalScore) {
DB db = new DB<Student>(".../student.db", "student");
if (db.open()) {
if (db.insertData(new Student(name, middleScore, finalScore))) {
model.addAttribute("message", "새 데이터를 추가했습니다.");
} else {
model.addAttribute("message", "데이터 추가에 실패했습니다.");
};
db.close();
} else {
model.addAttribute("message", "DB파일을 사용할 수 없습니다.");
}
return "message";
}
DB
// 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;
}
URL에 쿼리를 보내서 입력해보자.
http://localhost:8099/student/insert?name=홍길동&middleScore=100&finalScore=80
http://localhost:8099/student/insert?name=장보고&middleScore=70&finalScore=85
http://localhost:8099/student/insert?name=고길동&middleScore=90&finalScore=55
3. Update 만들기
HomeController
// 데이터 수정하기.
@RequestMapping(value = "/update", method = RequestMethod.GET)
public String insert(Locale locale, Model model,
@RequestParam("idx") int idx,
@RequestParam("name") String name,
@RequestParam("middleScore") int middleScore,
@RequestParam("finalScore") int finalScore) {
DB db = new DB<Student>(".../student.db", "student");
if (db.open()) {
if (db.insertData(new Student(idx, name, middleScore, finalScore))) {
model.addAttribute("message", "데이터를 수정했습니다.");
} else {
model.addAttribute("message", "데이터 수정에 실패했습니다.");
};
db.close();
} else {
model.addAttribute("message", "DB파일을 사용할 수 없습니다.");
}
return "message";
}
DB
// 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;
}
URL에 쿼리를 보내서 수정해보자.
http://localhost:8099/student/update?idx=1&name=홍길동&middleScore=100&finalScore=100
4. UTF-8 설정하기 & null 체크하기 & 숫자(numeric) 체크하기
STS 4 Spring Boot에서는 설정 안 해도 자동으로 UTF-8로 되지만 STS 3도 있으니까...
그리고 파라미터가 이름이 잘못 들어오거나 할 경우 400 에러가 뜨는데, 이런 것들이 보안 취약점이 되기 때문에 예외처리를 해준다.
UTF-8 처리
// 데이터 입력하기.
@RequestMapping(value = "/insert", method = RequestMethod.GET)
public String insert(Locale locale, Model model, HttpServletRequest request) {
try {
request.setCharacterEncoding("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String name = request.getParameter("name");
int middleScore = Integer.parseInt(request.getParameter("middleScore"));
int finalScore = Integer.parseInt(request.getParameter("finalScore"));
DB db = new DB<Student>(".../student.db", "student");
if (db.open()) {
if (db.insertData(new Student(name, middleScore, finalScore))) {
model.addAttribute("message", "새 데이터를 추가했습니다.");
} else {
model.addAttribute("message", "데이터 추가에 실패했습니다.");
};
db.close();
} else {
model.addAttribute("message", "DB파일을 사용할 수 없습니다.");
}
return "message";
}
null 체크하기 (방법 1) try~catch & 숫자(numeric) 체크하기
// 데이터 입력하기. try를 사용한 잘못된 파라미터 체크 & 문자열 숫자 형변환 가능 여부 검사하는 방법.
@RequestMapping(value = "/insert", method = RequestMethod.GET)
public String insert(Locale locale, Model model, HttpServletRequest request) {
try {
request.setCharacterEncoding("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
DB db = new DB<Student>(".../student.db", "student");
if (db.open()) {
try {
String name = request.getParameter("name");
int middleScore = Integer.parseInt(request.getParameter("middleScore"));
int finalScore = Integer.parseInt(request.getParameter("finalScore"));
if (db.insertData(new Student(name, middleScore, finalScore))) {
model.addAttribute("message", "새 데이터를 추가했습니다.");
} else {
model.addAttribute("message", "데이터 추가에 실패했습니다.");
};
} catch (Exception e) {
model.addAttribute("message", "데이터가 올바르지 않습니다.");
}
db.close();
} else {
model.addAttribute("message", "DB파일을 사용할 수 없습니다.");
}
return "message";
}
테스트용 URL
http://localhost:8099/student/insert?name=테스트1&middleScore=20&finalScore=20 // 정상인 경우
http://localhost:8099/student/insert?name=테스트2&middleScore=20&finalStore=20 // 파라미터 이름이 잘못 들어온 경우에 대한 null 체크
http://localhost:8099/student/insert?name=테스트3&middleScore=20a&finalScore=20 // 파라미터 이름은 정상이나 숫자가 들어와야 하는 곳에 문자가 들어오는 경우에 대한 예외처리
http://localhost:8099/student/insert?name=테스트3&middleScore=20&finalScore= // 파라미터 이름은 정상이나 숫자가 들어와야 하는 곳에 빈 값이 들어온 경우에 대한 예외처리
null 체크하기 (방법 2) if & 숫자(numeric) 체크하기
// 데이터 입력하기. if를 사용한 잘못된 파라미터 체크 & 문자열 숫자 형변환 가능 여부 검사하는 방법.
@RequestMapping(value = "/insert", method = RequestMethod.GET)
public String insert(Locale locale, Model model, HttpServletRequest request) {
try {
request.setCharacterEncoding("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
DB db = new DB<Student>(".../student.db", "student");
if (db.open()) {
if (request.getParameter("name") != null && // 파라미터 이름이 잘못 들어온 경우에 대한 null 체크
request.getParameter("middleScore") != null &&
isIntegerString(request.getParameter("middleScore")) && // 숫자로 형변환 가능한지를 체크 (파라미터 이름은 정상이나 숫자로 변환이 불가능하거나 빈 값에 대한 예외처리)
request.getParameter("finalScore") != null &&
isIntegerString(request.getParameter("finalScore")) &&
db.insertData(new Student(request.getParameter("name"), // 파라미터 가져오기
Integer.parseInt(request.getParameter("middleScore")),
Integer.parseInt(request.getParameter("finalScore"))))) {
model.addAttribute("message", "새 데이터를 추가했습니다.");
} else {
model.addAttribute("message", "데이터 추가에 실패했습니다.");
};
db.close();
} else {
model.addAttribute("message", "DB파일을 사용할 수 없습니다.");
}
return "message";
}
파라미터로 들어온 문자열이 숫자로 형변환 가능한지 아닌지를 검사하는 메소드를 만든다.
'java numeric string check' 등으로 검색한다.
// String이 숫자로 형변환이 가능한지 아닌지를 검사하는 메소드
private boolean isIntegerString(String numericString) {
try {
int result = Integer.parseInt(numericString);
return true;
} catch (Exception e) {
}
return false;
}
테스트용 URL
http://localhost:8099/student/insert?name=테스트1&middleScore=20&finalScore=20 // 정상인 경우
http://localhost:8099/student/insert?name=테스트2&middleScore=20&finalStore=20 // 파라미터 이름이 잘못 들어온 경우에 대한 null 체크
http://localhost:8099/student/insert?name=테스트3&middleScore=20a&finalScore=20 // 파라미터 이름은 정상이나 숫자가 들어와야 하는 곳에 문자가 들어오는 경우에 대한 예외처리
http://localhost:8099/student/insert?name=테스트3&middleScore=20&finalScore= // 파라미터 이름은 정상이나 숫자가 들어와야 하는 곳에 빈 값이 들어온 경우에 대한 예외처리
문자와 달리 숫자의 경우 형변환이 가능한지를 확인하는 것으로 숫자로 가능한 문자열인지에 대한 체크와 동시에 파라미터 이름은 정상이나 빈 값으로 들어오는 경우에 대한 예외처리를 동시에 할 수 있다.
발전 과제 : http://localhost:8099/student/insert?name=&middleScore=20&finalScore=20 // 파라미터 이름은 정상이나 문자가 들어와야 하는 곳에 빈 값이 들어온 경우에 대한 예외처리를 방법 1과 2 모두 처리하지 못 했다. replaceAll을 이용하면 처리가 되지만 이 경우 문자열 사이의 공백도 제거해버리기 때문에 사용할 수 없다. trim()으로 해보았으나 아예 " " 인 경우는 trim이 작동하지 않고 빈 문자열로 그냥 통과해버렸다.
update도 마찬가지로 바꿔주자. 위 방법 1을 사용하였으며, 변수를 생성하는 대신 바로 Student에 넣었다.
// 데이터 수정하기.
@RequestMapping(value = "/update", method = RequestMethod.GET)
public String update(Locale locale, Model model, HttpServletRequest request) {
try {
request.setCharacterEncoding("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
DB db = new DB<Student>(".../student.db", "student");
if (db.open()) {
try {
if (db.updateData(new Student(Integer.parseInt(request.getParameter("idx")),
request.getParameter("name"),
Integer.parseInt(request.getParameter("middleScore")),
Integer.parseInt(request.getParameter("finalScore"))))) {
model.addAttribute("message", "새 데이터를 수정했습니다.");
} else {
model.addAttribute("message", "데이터 수정에 실패했습니다.");
};
} catch (Exception e) {
e.printStackTrace();
model.addAttribute("message", "데이터가 올바르지 않습니다.");
}
db.close();
} else {
model.addAttribute("message", "DB파일을 사용할 수 없습니다.");
}
return "message";
}
테스트용 URL
http://localhost:8099/student/update?idx=19&name=공룡&middleScore=10&finalScore=13
idx에 들어가는 숫자는 DB를 보고 조절한다.
발전 과제 : idx가 존재하지 않는 값을 넣으면... 쿼리는 정상적으로 보내지기 때문에 데이터 수정에 실패했다고 뜨지 않고 수정했다고 뜬다...
방법 1과 방법 2를 기능별 분류하는 등 다양한 표현 코드에 대해서는 정리 3편에서 이어서 한다.
2020/09/06 - [개발자/Java] - Java (자바) CRUD 정리 3 static
'개발자 > Java' 카테고리의 다른 글
Java (자바) CRUD 정리 4 statement -> preparedStatement ★Inner Class★ (0) | 2020.09.06 |
---|---|
Java (자바) CRUD 정리 3 static ★클래스 메소드, 인스턴스 메소드★ (0) | 2020.09.06 |
Java (자바) CRUD 정리 1 Create Table(객체데이터, fieldString, Generic) (0) | 2020.09.02 |
전자정부 프레임 시작하기 2 (게시판 예제) (0) | 2020.07.09 |
전자정부 프레임 시작하기 1 (설치) (0) | 2020.07.08 |