
๐ close ์ ์๋ฏธ๋ ์๊ฒฉ์ ํต๋ณด๋ฅผ ํ๋ ์๋ฏธ๋ก GC๊ฐ ์ ์ญํ ์ ํด๋ ๋๋ค๋ ๋ง์ด๋ค.
๐ ๋ง์ฝ์ Connection ๊ฐ์ฒด๋ฅผ ์ธ์คํด์ค ๋ณ์๋ก ํ ๋นํ๊ฒ ๋๋ค๋ฉด ํ ์ฌ๋์ด 1๋ฒ ์์ ์ ํ๊ณ ์์๋ ๋ ๋ฒ์งธ ์ฌ๋์ด ์ค๊ฐ์ 2๋ฒ์์ ์ ํ๋ ค๊ณ ๋ค์ด์จ๋ค๋ฉด, ์ดํ close๋ฅผ ํ ๋๋ 1๋ฒ์์ ์ด ์๋๊ณ 2๋ฒ์์ ์ด close๊ฐ ๋๋ฏ๋ก GC๊ฐ ์ ์ญํ ์ ํ์ง ๋ชปํ๋ค.
๐ ๊ณ ๋ก, Connection, PreparedStatement, ResultSet๊ณผ ๊ฐ์ DB์ ์ฐ๊ฒฐํ๋ ๊ฐ์ฒด๋ค์ ์ง์ญ๋ณ์๋ก ์ ์ธํด์ผํ๋ค
๐ ๋ณ๋ ฌ ์ฒ๋ฆฌ ํ๊ฒฝ์์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ์ ๊ทผํ๋๋ผ๋ ํ๋ก๊ทธ๋จ์ด ์๋ํ ๋๋ก ์ ํํ๊ฒ ๋์ํ๋ ๊ฒ์ ๋งํ๋ค.
๐ Thread safe ๊ธฐ๋ฒ
๐ ๋๊ธฐํ ๋งค์ปค๋์ฆ : ๋๊ธฐํ๋ฅผ ํตํด ํ ์ค๋ ๋๊ฐ ์ ๊ทผ์ค์ธ ์์์ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์ ๊ทผํ์ง ๋ชปํ๋๋ก lock ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋๊ธฐํ๋ฅผ ๊ตฌํํ๋ค
๐ ๋ถ๋ณ๊ฐ์ฒด : ๊ฐ์ฒด์ ์ํ๊ฐ ๋ณ๊ฒฝ๋์ง ์๋๋ก ์ง์ญ๋ณ์๋ฅผ ์์ฑํ์ฌ ๋ฉ์๋๊ฐ ์คํ๋๋ ๋์์๋ง ์กด์ฌํ๋ค.
๐ ๊ธฐ์กด์ 100๊ฐ์ db๊ฐ์์๋, a์ฌ์ฉ์๊ฐ 30๊ฐ์ ๋ฐ์ดํฐ๋ฅผ db์ ๋ฃ๊ฒ ๋๋ฉด ์ธ์ ์์ ๋ณด๊ด์์ ๋ค์ด๊ฐ ์๋ค๊ฐ commit์ ํ๊ฒ๋๋ฉด ์ต์ข ์ ์ผ๋ก 130๊ฐ๊ฐ ๋๋ค. ๊ทธ๋ ๊ฒ ๋์๋ b์ฌ์ฉ์๊ฐ select๋ฅผ ํ๊ฒ ๋๋ฉด 130๊ฐ๋ก ํ์ธ์ด ๊ฐ๋ฅํ๋ค.
๐ JDBC๋ ๊ธฐ๋ณธ์ ์ผ๋ก auto-commit์ด๊ธฐ ๋๋ฌธ์ ์๋์ผ๋ก ๋ฐ์๋๋ค.
๐ ๋ฐ์ดํฐ๋ฅผ insertํ ํ์ last-insert id ๋ฅผ ๋ฌผ์ด๋ณด๋ฉด ๋ง์ง๋ง์ผ๋ก ์ด ์ธ์ ์์ ๋ง๋ค์ด์ง auto incresement ์ ๊ฐ์ ๊ฐ์ ธ์จ๋ค. ๋ง์ฝ insertํ๊ณ ์ฐ๊ฒฐ์ ๋์ ๋ค์ ์๋ก ์ฐ๊ฒฐํ ์ดํ์ last-linsert id ๋ฅผ ๋ฌผ์ด๋ณด๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
๐ ์ฌ๋ฌ๋ฒ์ sql์ ์คํํด์ผ ํ ๋๋ con.setAutocommit(false)๋ฅผ ํด๋๊ณ
์์
์ด ๋๋ ์ดํ์ con.commit( )์ ํด์ฃผ๋๊ฑธ ๊ถ์ฅํ๋ค. ์ถ๊ฐ์ ์ผ๋ก ์์ธ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ฉด rollback์ ์งํํ๋ค.
๐ ์ด๋ฌํ ์ฌ๋ฌ๊ฐ์ ์์ ์ด ํ๋์ ๋จ์ ์์ ์ด ๋๋๊ฒ์ Transcation์ด๋ผ๊ณ ํ๋ค.
๐ null์ ์ฒ๋ฆฌํ๋ ์๋ก์ด ๋ฐฉ๋ฒ
๐ Optional์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์กฐํํ ๊ฒฐ๊ณผ๊ฐ null์ผ ๋์ ์ฒ๋ฆฌ๋ฅผ ๊ฐ์ํํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, get(Integer tno) ๋ฉ์๋์์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์กฐํํ ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด Optional.empty()๋ฅผ ๋ฐํํ์ฌ ํธ์ถ์์๊ฒ ๊ฒฐ๊ณผ๊ฐ ์์์ ๋ช
ํํ ์ ๋ฌํฉ๋๋ค.
๐ TodoRegisterController์ Builder : ์ฌ์ฉ์ ์
๋ ฅ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก ์๋ก์ด TodoVO ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ฌ์ฉ์๊ฐ ์ ์ถํ ํผ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ฒด๋ก ๋ณํํ ๋ ์ฌ์ฉ๋๋ฉฐ, ๊ฐ ํ๋๋ฅผ ๋ช
์์ ์ผ๋ก ์ค์ ํฉ๋๋ค.
๐ TodoDAO์ Builder: ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ฐ์ ธ์จ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ์ผ๋ก TodoVO ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ปฌ๋ผ๋ค์ TodoVO ๊ฐ์ฒด์ ๊ฐ ์์ฑ์ ๋งคํํ๊ณ , ๋ฐ์ดํฐ๋ฒ ์ด์ค ์กฐํ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ฒด๋ก ๋ณํํ ๋ ์ ์ฉํฉ๋๋ค.
๐ ํน์ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ ์งํฉ์์ ๊ฐ ํ์ ์๋ฒ์ ๋ํ๋ด๋ ๊ฐ์์ปฌ๋ผ.
๐ rownum์ ์ ๋ ฌ ์์ด ๋ฐํ๋ ์์๋๋ก ํ์ ํ ๋น๋๋ค.

๐ ์ค๋ฆ์ฐจ์ ์ ๋ ฌํ rownum ๋ถ์ฌ

๐๋ด๋ฆผ์ฐจ์ ์ ๋ ฌํ rownum๋ถ์ฌ
๐ ํด๋น ์ฝ๋๋ ๊ฒฐ๊ณผ ์งํฉ์์ ์ฒซ ๋ฒ์งธ ํ์ ์ฐพ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉ๋๋ค.
๐ ROWNUM์ ๊ฒฐ๊ณผ ์งํฉ์ด ์ต์ข ์ ์ผ๋ก ์ ๋ ฌ ๋ฐ ํํฐ๋ง ๋ ์ดํ ํ ๋น๋๋ฏ๋ก ํด๋น ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ํ ๋๋ก ์ฒซ ๋ฒ์งธ ํ์ ์ ํํ ์ ์๋ค.
๐ db ์์ rownum์ด 10๊ณผ 20์ฌ์ด์ธ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํ๊ณ ์ถ์๋
select ROWNUM rn, bno, title
from tbl_board
where rn <= 20 and rn > 10
order by bno desc
๐ ํด๋น ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฒฐ๊ณผ๊ฐ์ด ๋์ค์ง ์๋ ์ด์ ๋ from ์ ๋ท ๋ถ๋ถ์ ๋ฐ์ดํฐ ์งํฉ์ ์๋ฏธ
select
*
from
(
select ROWNUM rn, bno, title
from tbl_board
where rownum <= 20
order by bno desc
)
where rn > 10
;
๐ from ๋ค์ ์ค๋ ๊ฐ๋ค์ ์งํฉ์ผ๋ก ๋์ค๊ธฐ ๋๋ฌธ์ด๋ค. where์ ์ ๋ดค์๋ rownum์ด 10 ๋ณด๋ค ํฐ ๊ฐ์ผ๋ ๊ฐ์ ธ์ฌ ์ ์๋๋ฐ ํด๋น ํ ์ด๋ธ์ rownum์ ๋ ฌ๋ก ๋ณด์์๋ ์ฒซ๋ฒ์งธ๋ rownum์ด 1๋ฒ์ด๋ค. ๊ทธ๋ฌ๋ฉด ํด๋น ๊ฐ์ where์กฐ๊ฑด์ ๋ง์ง์์์ ์ถ๋ ฅ์ด ์๋๊ณ ๋๊ธด๋ค๊ณ ์น๋ฉด ๋ค์ ์ 2๋ฒ์ด ์๋๊ณ ๋ 1๋ฒ๊ฐ์ด ๋๋๊ฒ ์ด๋ฏ๋ก where์ ์ ๋ง๋ rownum๊ฐ์ ๋์ค์ง ์์ ๊ฒฐ๊ณผ ๊ฐ์ด ์๋์ค๋๊ฒ์ด๋ค.
๐ oracle์์ ํ์ด์นญ ์ฒ๋ฆฌ๋ฅผ ํ๊ธฐ ์ํ ๋ฐฉ๋ฒ
select
*
from
(
select ROWNUM rn, bno, title
from tbl_board
where rownum <= 20
order by bno desc
)
where rn > 10
;
๐ Oracle db์์ ๊ฐ ํ์ ์๋ณํ๋ ์ ์ผํ ๊ฐ.

๐ โAAARyโฆโ๊ฐ์ด RowID๋ก ํด๋น ์ฝ๋๋ฅผ ์ด์ฉํด์ ์ํ๋ ROW์ ๊ฐ์ ์ถ๋ ฅํ ์ ์๋ค.
๋ก๊ทธ๋ ๋ฒจ / Appender / Layout
๋ก๊ทธ๋ ๋ฒจ
๐ ๋ก๊ทธ๋ ๋ฒจ์ ์ข
๋ฅ๋ trace, debug, info, warining, error, fatal
๊ฐ๋ฐ์ ๋ฐ๋ผ์ ์ด๋ค ๋ ๋ฒจ๊น์ง ์ถ๋ ฅ์ด ๋๋์ง ์ ์ฉํ์ฌ
์ฌ๊ฐํ ์๋ฌ๋ง ๋ฐ๋ก ํ์ธํ ์ ์๋ค.
Appender๋ ๋ก๊ทธ๋ฅผ ๊ธฐ๋กํ๋๊ฒ.
๐ ConsoleAppender ๋ ์ฝ์์ ๊ธฐ ๋ก์ด ๋๋๊ฒ.
๐ DailyRollingFileAppender ๋ ํ์ผ์ ๊ธฐ๋ก์ด ๋๋๊ฒ.
Layout
๐ ํฌ๋ฉงํ ์ญํ , ๋ช๋ฒ์งธ ๋ผ์ธ์์ log๋ฅผ ๋จ๊ฒผ๋์ง ํ์ธ์ด ๊ฐ๋ฅํจ
public class TodoListController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String pageStr = req.getParameter("page"); //url์ฃผ์์ฐฝ์ example.com/todo/list?page=21 ์ ํด๋นํ๋ 21์ ๊ฐ์ ๊ฐ์ ธ์ด
log.info("pageStr: " + pageStr);
int page = StringUtil.getInt(pageStr, 1);
//ํ์ด์ง ์ด์ํ๋ฉด 1ํ์ด๋ก ๋์ด๊ฐ๊ธฐ
try {
int total = TodoDAO.INSTANCE.getTotal();
//์์ธ์ฒ๋ฆฌ๋ฅผ ํด์ค์ผํ๋๋ฐ ๋์ง๋ฉด ์ค๋ฒ๋ผ์ด๋ฉ ์์์ ๋ฌธ์ ๊ฐ ์๊น ๊ทธ๋์ ์ผ๋จ try-catch
Pageinfo pageInfo = new Pageinfo(page, 10, total);
//ํ์ฌ / ๊ฒ์๋ฌผ๊ฐ์ / ๋ฐ์ดํฐ๊ฐ์
List<TodoVO> todoList = TodoDAO.INSTANCE.list(pageInfo.getPage());
//ํด๋นํ์ด์ง๋ฅผ ์ฃผ๋ฉด todoList์ ๊ฐ์ ์ค๋ค.
req.setAttribute("todolist", todoList);
req.setAttribute("pageInfo", pageInfo);
//๋๋ฏธ๋ฐ์ดํฐ๋ฅผ jsp๋ก ์ฎ๊ธฐ๊ธฐ
req.getRequestDispatcher("/WEB-INF/todo/list.jsp").forward(req, resp); //view
//list.jsp๋ก ์ถ๋ฐ
}catch (Exception e) {
e.printStackTrace();
}
}
}
@WebServlet(value = "/todo/register")
@Log4j2
public class TodoRegisterController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
log.info("todo register doGet");
req.getRequestDispatcher("/WEB-INF/todo/register.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//step1 - ๋ธ๋ผ์ฐ์ ์ ์ ๋ฌํ๋ ๋ฐ์ดํฐ ์์ง
log.info("todo register doPost");
String title = req.getParameter("title");
String writer = req.getParameter("writer");
log.info("title :" + title);
log.info("writer :" + writer);
//step2 - ๋ฐ์ดํฐ ๊ฐ๊ณตํด์ VO, DTO ๊ฐ์ฒด๋ฅผ ์์ฑ
TodoVO vo = TodoVO.builder()
.title(title)
.writer(writer)
.build();
log.info("todoVO: " + vo);
//step3 - service, DAO์๊ฒ ์ฒ๋ฆฌ๋ฅผ ๋ถํ
try {
Integer tno = TodoDAO.INSTANCE.insert(vo);
//step4 - ๊ฒฐ๊ณผ ์ ์ก Redirect
resp.sendRedirect("/todo/list?tno=" + tno);
// ์ ์ฒ๋ฆฌํ๋ฉด listํ๋ฉด์ผ๋ก redirect
} catch (Exception e) {
//step4 - ๊ฒฐ๊ณผ ์ ์ก insert ์์ธ ๋ฐ์์ Redirect
resp.sendRedirect("/todo/register?error=input");
//์๋ชป ์ฒ๋ฆฌํ๋ฉด
}
}
}
@WebServlet(value = {"/todo/get","/todo/edit"})
@Log4j2
public class TodoReadController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
log.info("doGet");
String uri = req.getRequestURI(); //ํ์ฌ ๋ธ๋ผ์ฐ์ ์ uri์ฐฝ์ด ์ด๋ค๊ฑด์ง ์์๋ณด๋ ๋ฐฉ๋ฒ
// /todo/get ์ผ๋ ๋ง์ง๋ง ์ฌ๋์ฌ๋ฅผ ๋์ด๋ด๋ฉด get ํน์ edit ์ ๊ฐ์ ธ์จ๋ค.
String jspName = uri.substring(uri.lastIndexOf('/') + 1);
String tnoStr = req.getParameter("tno"); //์ ๋ณด๊ฐ์ ธ์ค๋๊ฑฐ ๋ฌธ์์ด๋ก ๊ฐ์ ธ์ค๋๊น ๋ฐ์์ ์ซ์๋ก ๋ฐ๊ฟ์ค์ผํจ
Integer tno = StringUtil.getInt(tnoStr,-1); //์ค๋ฅ๋๋ฉด -1๋ก ๋ฐํํ๊ธฐ
log.info("tno: "+tno);
try {
Optional<TodoVO> result = TodoDAO.INSTANCE.get(tno);
TodoVO vo = result.orElseThrow(); //์์ผ๋ฉด ์์ธ๊ฐ ์ฒ๋ฆฌ๋๊ฒ, ์์ผ๋ฉด ์๋๋ก ๋น ์ง๊ฒ๋จ ๋ด๋ถ์ ์์ธ๊ธฐ๋ฅ์ด ๋ดํฌ๋์ด์๋ ๋ฉ์๋
req.setAttribute("todo", vo); //vo์ ๊ฐ์ jsp์์ todo๋ผ๋ ์ด๋ฆ์ผ๋ก ์ฌ์ฉํ ๊ฑฐ์ผ.
req.getRequestDispatcher("/WEB-INF/todo/"+jspName+".jsp").forward(req, resp);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String uri = req.getRequestURI(); //ํ์ฌ ๋ธ๋ผ์ฐ์ ์ uri์ฐฝ์ด ์ด๋ค๊ฑด์ง ์์๋ณด๋ ๋ฐฉ๋ฒ
String job = uri.substring(uri.lastIndexOf('/') + 1);
if(job.equals("get")){ //get์ผ๋ก ๋ค์ด์ค๊ฒ ๋๋ค๋ฉด list๋ก ๋ณด๋ด๋ฒ๋ฆฌ๊ธฐ
resp.sendRedirect("/todo/list");
return;
}
String tnoStr = req.getParameter("tno");
Integer tno = StringUtil.getInt(tnoStr,-1);
String title = req.getParameter("title");
String writer = req.getParameter("writer");
TodoVO vo = TodoVO.builder()
.tno(tno)
.title(title)
.writer(writer)
.build();
try {
boolean result = TodoDAO.INSTANCE.update(vo);
resp.sendRedirect("/todo/get?tno="+tno);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
//์ ์ฝ๋์์ @WebServlet(value="/todo/remove") ์ด๋
ธํ
์ด์
์ /todo/remove ๊ฒฝ๋ก๋ก ๋ค์ด์ค๋ ์์ฒญ์
//์ด ์๋ธ๋ฆฟ ํด๋์ค(TodoRemoveController)๊ฐ ์ฒ๋ฆฌํ๊ฒ ๋ค๋ ๊ฒ์ ๋ํ๋.
@WebServlet(value= "/todo/remove")
@Log4j2
public class TodoRemoveController extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
log.info("doPost");
String tnoStr = req.getParameter("tno");
Integer tno = StringUtil.getInt(tnoStr,-1);
//์ญ์ ๊ฐ ๋๋ฉด true or false๊ฐ ๋๋ค๋ ๊ฐ์
boolean result = false;
try {
result = TodoDAO.INSTANCE.delete(tno);
} catch (Exception e) {
throw new RuntimeException(e);
}
//์ญ์ ๊ฐ ๋๋ฉด ๋ฆฌ์คํธ ํ๋ฉด
//redirectํ ๋๋ get๋ฐฉ์๋ฐ์ ๋ชป์ฐ๋๊น ์ฟผ๋ฆฌ์คํธ๋ง ์จ์ค์ผํจ
resp.sendRedirect("/todo/list?result="+result);
}
}
@Log4j2
public enum TodoDAO {
INSTANCE;
public Integer insert(TodoVO todoVO) throws Exception {
//insert update delete๋ ๋๊ฒ integer ํน์ boolean์ ์ฌ์ฉํ๋ค.
//return ๊ฐ์ผ๋ก ๋๋ถ๋ถ tno์ ๊ฐ์ ์ ์๋ฅผ ์ ๋ฌํจ.
String sql = "insert into tbl_todo (title, writer) values (?,?)";
@Cleanup Connection con = ConnectionUtil.INSTANCE.getDs().getConnection();
@Cleanup PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, todoVO.getTitle());
ps.setString(2, todoVO.getWriter());
//๋งค๊ฐ๋ณ์๋ก todoVO๋ฅผ ๋ฐ๊ธฐ ๋๋ฌธ์ todoVO์ get๊ฐ์ ์ฌ์ฉํ๋ค.
int count = ps.executeUpdate();
//์
๋ฐ์ดํธ๋ฅผ ์คํํ์ฌ count๋ก ๋ฐ๋ ์ด์ ๋ dml์ count๋ก ๋ฐ์์ผํจ.
if(count != 1){ //count๊ฐ์ด 1์ด ์๋๋ฉด ์๋ชป๋๊ฒ์ด๋๊น.
throw new Exception("Abnormal insertion");
}
ps.close(); //ps๋ฅผ ๋ค์ ์ฌ์ฉํด์ผํ๋ฏ๋ก ์ฒซ๋ฒ์งธ ps๋ฅผ ๋ซ๊ณ
ps = con.prepareStatement("select LAST_INSERT_ID()"); //๋๋ฒ์งธ ps๋ฅผ ๋ค์ ์ฌ์ฉํ๋ค.
//๋ง์ง๋ง์ ๋ฃ์ tno๊ฐ์ ๊ฐ์ ธ์จ๋ค.
@Cleanup ResultSet rs = ps.executeQuery();
rs.next();
Integer tno = rs.getInt(1);
log.info("TNO:..." +tno);
con.commit(); //ํธ๋์ญ์
์ปค๋ฐ
con.setAutoCommit(true); //ํธ๋์ญ์
์คํ ์ปค๋ฐ
return tno;
}
//ํ์ด์ง์ total count๊ฐ์ ๊ฐ์ ธ์์ผํด์ db์ ์ฐ๊ฒฐํด์ค์ผํจ
public List<TodoVO> list(int page) throws Exception{ //arraylist๋ ํด๋์ค list ๋ ์ถ์์ ์ด๋๊น ์ฌ์ฉํจ
int skip = (page -1) *10; //db์์์ limit
String query = """
select * from tbl_todo
where
tno > 0
and
delflag = false
order by tno desc
limit ?,10
""";
//limit ์ ์ฒซ๋ฒ์งธ๋ฅผ ๋ณ์์ฒ๋ฆฌํ๊ธฐ์ํด์ db์์์๋ limit๊ฐ์ ๊ฐ๋ฐ์ ์๋ค์ด๊ฐ๋๊น.
//1ํ์ด์ง๋ 1๋ฒ๋ถํฐ 10๋ฒ๊น์ง ์์ผ๋ฏ๋ก limit 0 10
//2ํ์ด์ง๋ 11๋ฒ๋ถํฐ 20๋ฒ๊น์ง ์์ผ๋ฏ๋ก limit 10 10
//๊ทธ๋ฌ๋ฉด limit (page-1)*10 10
@Cleanup Connection con = ConnectionUtil.INSTANCE.getDs().getConnection(); //connection pool์ ์ฌ์ฉํ๊ธฐ ์ํจ.
@Cleanup PreparedStatement ps = con.prepareStatement(query);
ps.setInt(1, skip); //์ฒซ๋ฒ์งธ ๋ฌผ์ํ์ ๊ฐ์ skip์ด์ผ.
@Cleanup ResultSet rs = ps.executeQuery();
//ResultSet ์๋ฐ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก ๊ฐ์ ธ์จ ๊ฒฐ๊ณผ๋ฅผ ์งํฉ์ผ๋ก ๋ํ๋.
//dml์ผ ๊ฒฝ์ฐ์๋ ์ฌ์ฉํ์ง ์์.
List<TodoVO> list = new ArrayList<>(); //๋ฐ์ดํฐํ์
์ด List<TodoVO> ์ธ ArrayList ์์ฑ
//๋ฆฌ์คํธ ํ๋ฉด์์ ์ฌ๋ฌ ๊ฐ์ Todo ํญ๋ชฉ์ ๊ฐ์ ธ์ค๋ ๊ฒฝ์ฐ์ ์ฌ์ฉ
while (rs.next()) { //re.next() ๋ ์ฝ๋ ํ์ค์ฉ ๋๊ธฐ๊ธฐ
TodoVO vo = TodoVO.builder()
.tno(rs.getInt("tno")) //tno์๋ค๊ฐ tno ์ปฌ๋ผ๊ฐ์ ์ฝ์ด์ ๋ฃ์
.title(rs.getString("title"))
.writer(rs.getString("writer"))
.regDate(rs.getTimestamp("regdate"))
.modDate(rs.getTimestamp("moddate"))
.delFlag(rs.getBoolean("delflag"))
.build();
list.add(vo); //list์ ํ์ค์ฉ ์ถ๊ฐํ๊ธฐ
}
return list;
}
public int getTotal() throws Exception {
log.info("GetTotal");
String query = "select count(tno) from tbl_todo where tno > 0 and delflag = false";
@Cleanup Connection con = ConnectionUtil.INSTANCE.getDs().getConnection();
@Cleanup PreparedStatement ps = con.prepareStatement(query);
@Cleanup ResultSet rs = ps.executeQuery();
rs.next(); //์์ ์ธ๋์๋ ์ ๋ณด๋ ์ฝ์ง์๊ณ ํ๊ฐ ๋๊ธฐ๊ธฐ tno count 85016 ์ฝ๊ธฐ์ํด์
//rs์ count๋ผ๋ ํ๊ฐ์ ํ์ด ํ์ํ๋ฐ, ์ฒซ๋ฒ์งธ๋ ๋ฒ๋ฆฌ๊ณ ๋๋ฒ์งธ์ ๊ทธ ์นด์ดํธ์ ๊ฐ์๊ฐ ์ ํ์์.
int total = rs.getInt(1);
//getInt๋ ResultSet์์ ์ ๊ณตํ๋ ๋ฉ์๋๋ก ํด๋น๋๋ ์ธ๋ฑ์ค์ ๊ฐ์ ์ ์๋ก ๊ฐ์ ธ์จ๋ค.
return total;
}
public Optional<TodoVO> get(Integer tno) throws Exception {
final String query = """
select tno, title, writer, regdate, moddate, delflag
from
tbl_todo
where tno = ?
""";
@Cleanup Connection con = ConnectionUtil.INSTANCE.getDs().getConnection();
@Cleanup PreparedStatement ps = con.prepareStatement(query);
ps.setInt(1, tno);
@Cleanup ResultSet rs = ps.executeQuery();
if(!rs.next()){ //์๋ ์ฒซ๋ฒ์งธ๋ next๋ก ๋๊ธฐ๋๋ฐ, ๊ทธ ์ฒซ๋ฒ์งธ๊ฐ ์๋ค๋ฉด.
return Optional.empty();
}
TodoVO vo = TodoVO.builder()
.tno(rs.getInt("tno")) //tno์๋ค๊ฐ tno ์ปฌ๋ผ๊ฐ์ ์ฝ์ด์ ๋ฃ์
.title(rs.getString("title"))
.writer(rs.getString("writer"))
.regDate(rs.getTimestamp("regdate"))
.modDate(rs.getTimestamp("moddate"))
.delFlag(rs.getBoolean("delflag"))
.build();
return Optional.of(vo);
}
public boolean delete(Integer tno) throws Exception {
String sql = "update tbl_todo set moddate = now() , delflag = true where tno = ?";
@Cleanup Connection con = ConnectionUtil.INSTANCE.getDs().getConnection();
@Cleanup PreparedStatement ps = con.prepareStatement(sql);
ps.setInt(1, tno);
int count = ps.executeUpdate(); //dml์ ๋ช๊ฑด์ด ๋ณ๊ฒฝ๋์๋์ง int๋ก ์ถ๋ ฅ๋จ
return count == 1; //count๊ฐ 1์ด๋ฉด true
}
public boolean update(TodoVO todoVO) throws Exception {
String sql = """
update tbl_todo
set
title = ?,
writer = ?,
moddate = now()
where tno = ?
""";
@Cleanup Connection con = ConnectionUtil.INSTANCE.getDs().getConnection();
@Cleanup PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, todoVO.getTitle());
ps.setString(2, todoVO.getWriter());
ps.setInt(3, todoVO.getTno());
int count = ps.executeUpdate();
return count == 1 ? true : false;
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@include file="../includes/header.jsp"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>Edit Page</h1>
${todo}
<form action = "/todo/edit" method="post">
<div>
<label>TNO</label>
<input type="text" name="tno" value="${todo.tno}" readonly> <!-- ์์ ํ ๊ฒ ์๋๋๊น readonly-->
</div>
<div>
<label>TITLE</label>
<input type="text" name="title" value="${todo.title}">
</div>
<div>
<label>WRITER</label>
<input type="text" name="writer" value="${todo.writer}">
</div>
<div>
<button>MODIFY</button>
</div>
</form>
<form action = "/todo/remove" method="post">
<input type="hidden" name="tno" value="${todo.tno}">
<button>REMOVE</button>
</form>
<%@include file="../includes/footer.jsp"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@include file="../includes/header.jsp"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
${todo}
<%--<a href="/todo/edit?tno=${todo.tno}">Modify/Delete</a>--%>
<br>
<form action ="/todo/edit?tno=${todo.tno}" method="get">
<input type="hidden" name="tno" value="${todo.tno}">
<button type="submit" name="tno" class="btn btn-warning" onclick="submitForm()">Modify/Deletery</button>
</form>
<br><br>
<script>
function submitForm() {
document.getElementById("editForm").submit();
}
</script>
<%@include file="../includes/footer.jsp"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@include file="../includes/header.jsp"%>
<style>
.msg {
width: 200px;
height: 100px;
background-color: lightblue;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: none; /* Initially hidden */
opacity: 0; /* Initially transparent */
animation: showHide 3s forwards; /* 3 seconds animation */
}
@keyframes showHide {
0% {
display: block; /* Make it visible */
opacity: 0;
}
10% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
opacity: 0;
display: none; /* Hide it again */
}
}
</style>
<h1>todo list page</h1>
<a href ="/todo/register">Todo Register</a>
<c:if test="${param.tno != null || param.result}"> <!--๋ฑ๋ก์ ํ ์ดํ์ url์ ๋จ๋ tno๋ฅผ ์ด์ฉํ๊ธฐ-->
<div class="msg">
<h1>์ฒ๋ฆฌ๊ฒฐ๊ณผ ์
๋๋ค.</h1>
</div>
</c:if>
<ul>
<c:forEach items = "${todolist}" var="todo">
<li>
<div>
<div>${todo.tno}</div>
<div>
<a href="/todo/get?tno=${todo.tno}"> ${todo.title} </a>
</div>
</div>
</li>
</c:forEach>
</ul>
<ul class="pagination">
<c:if test="${pageInfo.prev}"> <!-- ์ด์ ํ์ด์ง --> <!-- ํ์ฌ 11์์ 20ํ์ด์ง๊ฐ ๋ณด์ธ๋ค๊ณ ํ ๋ start=11-->
<li class="page-item"><a class="page-link" href="/todo/list?page=${pageInfo.start-1}">Previous</a></li>
</c:if>
<c:forEach begin="${pageInfo.start}" end="${pageInfo.end}" var="num">
<li class="page-item ${pageInfo.page == num ? 'active':''}"><a class="page-link" href="/todo/list?page=${num}">${num}</a></li>
</c:forEach> <!-- ํ์ฌ page์ num์ด ๊ฐ์ผ๋ฉด ํ๋์์ผ๋ก ๋ณ๊ฒฝ-->
<c:if test="${pageInfo.next}"> <!-- ๋ค์ํ์ด์ง --> <!-- ํ์ฌ 1์์ 10ํ์ด์ง๊ฐ ๋ณด์ธ๋ค๊ณ ํ ๋ end=10-->
<li class="page-item"><a class="page-link" href="/todo/list?page=${pageInfo.end+1}">Next</a></li>
</c:if>
</ul>
<script>
window.onload = function() {
document.querySelector('.msg').style.display = 'block';
};
</script>
<%@include file="../includes/footer.jsp"%>
<%@include file="../includes/header.jsp"%>
<div class="card" style="margin: 3em">
<p>Todo Register Page</p>
<div class="card-body">
<form action="/todo/register" method="post">
<div class="mb-3">
<label class="form-label">Title</label>
<input type="text" name="title" class="form-control" placeholder="name@example.com">
</div>
<div class="mb-3">
<label class="form-label">Writer</label>
<input type="text" name="writer" class="form-control" placeholder="user">
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary">SAVE</button>
</div>
</form>
</div>
</div>
<%@include file="../includes/footer.jsp"%>