在核心J2EE模式中是这样介绍DAO模式的:为了建立一个健壮的J2EE应用,应该将所有对数据源的访问操作抽象封装在一个公共API中。用程序设计的语言来说,就是建立一个接口,接口中定义了此应用程序中将会用到的所有事务方法。在这个应用程序中,当需要和数据源进行交互的时候则使用这个接口,并且编写一个单独的类来实现这个接口在逻辑上对应这个特定的数据存储。
DAO模式是标准的J2EE设计模式之一.开发人员使用这个模式把底层的数据访问操作和上层的商务逻辑分开。一个典型的DAO实现有下列几个组件:
- 一个DAO工厂类;
- 一个DAO接口;
- 一个实现DAO接口的具体类;
- 数据传递对象(有些时候叫做值对象).
第一步,建立数据传递对象(pojo)Book实体类
package com.wise.tiger.pojo; //********** import *************// /** * 图书实体类(在Dao模式中用于各层消息--数据传递) */ public class Book{ /** * id */ private Integer id; /** * 图书名称 */ private String title; /** * 图书作者 */ private String author; /** * 图书价格 */ private float price; /** * 出版社信息 */ private String publisher; /** * 图书简介 */ private String intro; /** * 出版日期 */ private LocalDate publishDate = LocalDate.now(); //********************* setter and getter *******************// }
sql脚本
drop database if exists db_book; create database db_book; use db_book; create table tb_book( id int primary key auto_increment, title varchar(20) not null, author varchar(20), price decimal(10,2), publisher varchar(30), intro text, publish_date date )
一个DAO接口
package com.wise.tiger.dao; //***************** import ******************// /** * 图书dao接口 * @Author: <a href="mailto:1020zhaodan@163.com">Adan</a> * @Date: 2019/4/15 0015 10:59 * @version: 1.0-SNAPSHOT */ public interface BookDao { /** * 保存一本图书 * @param book 图书信息 */ void persistent(Book book); /** * 根据id删除图书信息 * @param id id */ void delete(Integer id); /** * 修改图书信息 * @param book 修改后的图书信息 */ void update(Book book); /** * 根据id获取图书信息 * @param id id * @return 图书信息 */ Book search(Integer id); /** * 加载全部图书信息,未分页 * @return 全部图书信息 */ List<Book> search(); /** * 获取图书总记录数 * @return 总记录数 */ long getCount(); }
Dao接口具体实现类
package com.wise.tiger.dao.impl; //***************** import ******************// public class BookDaoImpl implements BookDao { @Override public void persistent(Book book) { var sql = "INSERT INTO tb_book(title,author,price,publisher,intro,publish_date) VALUES (?,?,?,?,?,?)"; //采用try-with-resource语法确保相关资源的释放 try(var conn = DBHelper.getConnection();//1.通过工具类获取连接 var ptst = conn.prepareStatement(sql)){//2.预编译语句对象 //对预编译语句?占位符进行设置参数 ptst.setString(1,book.getTitle()); ptst.setString(2,book.getAuthor()); ptst.setFloat(3,book.getPrice()); ptst.setString(4,book.getPublisher()); ptst.setString(5,book.getIntro()); ptst.setString(6,book.getPublishDate()); //执行dml语句 ptst.executeUpdate(); }catch (SQLException e){ e.printStackTrace(); } } @Override public void delete(Integer id) { var sql = "DELETE FROM tb_book WHERE id = ?"; //采用try-with-resource语法确保相关资源的释放 try(var conn = DBHelper.getConnection();//1.通过工具类获取连接 var ptst = conn.prepareStatement(sql)){//2.预编译语句对象 //对预编译语句?占位符进行设置参数 ptst.setInt(1,id); //执行dml语句 ptst.executeUpdate(); }catch (SQLException e){ e.printStackTrace(); } } @Override public void update(Book book) { var sql = "UPDATE tb_book SET title = ?,author=?,price=?,publisher=?,intro=?,publish_date=? WHERE id = ?"; //采用try-with-resource语法确保相关资源的释放 try(var conn = DBHelper.getConnection();//1.通过工具类获取连接 var ptst = conn.prepareStatement(sql)){//2.预编译语句对象 //对预编译语句?占位符进行设置参数 ptst.setString(1,book.getTitle()); ptst.setString(2,book.getAuthor()); ptst.setFloat(3,book.getPrice()); ptst.setString(4,book.getPublisher()); ptst.setString(5,book.getIntro()); ptst.setString(6,book.getPublishDate()); ptst.setInt(7,book.getId()); //执行dml语句 ptst.executeUpdate(); }catch (SQLException e){ e.printStackTrace(); } } @Override public Book search(Integer id) { Book book = null; var sql = "SELECT id,title,author,price,publisher,intro,publish_date FROM tb_book WHERE id = ?"; //采用try-with-resource语法确保相关资源的释放 try(var conn = DBHelper.getConnection();//1.通过工具类获取连接 var ptst = conn.prepareStatement(sql)){//2.预编译语句对象 //对预编译语句?占位符进行设置参数 ptst.setInt(1,id); //执行dql语句,返回结果集 var rs = ptst.executeQuery(); //处理结果集,结果集中列对应的值设置为book实体对应的属性值 if(rs.next()){ book = new Book(); book.setId(rs.getInt("id")); book.setTitle(rs.getString("title")); book.setAuthor(rs.getString("author")); book.setPrice(rs.getFloat("price")); book.setPublisher(rs.getString("publisher")); book.setIntro(rs.getString("intro")); book.setPublishDate(LocalDate.ofInstant(new Date(rs.getDate("publish_date").getTime()).toInstant(),ZoneId.systemDefault()));//java.sql.Date转LocalDate } }catch (SQLException e){ e.printStackTrace(); } return book; } @Override public List<Book> search() { List<Book> books = new ArrayList<>(); var sql = "SELECT id,title,author,price,publisher,intro,publish_date FROM tb_book"; //采用try-with-resource语法确保相关资源的释放 try(var conn = DBHelper.getConnection();//1.通过工具类获取连接 var ptst = conn.prepareStatement(sql)){//2.预编译语句对象 //执行dql语句,返回结果集 var rs = ptst.executeQuery(); //处理结果集,结果集中列对应的值设置为book实体对应的属性值 while(rs.next()){ var book = new Book(); book.setId(rs.getInt("id")); book.setTitle(rs.getString("title")); book.setAuthor(rs.getString("author")); book.setPrice(rs.getFloat("price")); book.setPublisher(rs.getString("publisher")); book.setIntro(rs.getString("intro")); book.setPublishDate(LocalDate.ofInstant(new Date(rs.getDate("publish_date").getTime()).toInstant(),ZoneId.systemDefault()));//java.sql.Date转LocalDate books.add(book); } }catch (SQLException e){ e.printStackTrace(); } return books; } @Override public long getCount() { var count = 0; var sql = "SELECT COUNT(1) FROM tb_book"; try(var conn = DBHelper.getConnection();//1.通过工具类获取连接 var ptst = conn.prepareStatement(sql)){//2.预编译语句对象 //执行dql语句,返回结果集 var rs = ptst.executeQuery(); //处理结果集,结果集中列对应的值设置为book实体对应的属性值 if(rs.next()){ count = rs.getLong(1); } }catch (SQLException e){ e.printStackTrace(); } return count; } }
Dao工厂类(非必须):针对这个Dao可能有多个实现,我们需要根据其外部配置动态获取dao的实例,该工厂专门用于创建Dao实例
public class DaoFactory { private static BookDao bookDao = null; private static DaoFactory instance = new DaoFactory(); private DaoFactory() { try { Properties prop = new Properties(); InputStream inStream = DaoFactory.class.getClassLoader() .getResourceAsStream("daoconfig.properties"); prop.load(inStream); var bookDaoClass = prop.getProperty("bookDaoClass"); Class clazz = Class.forName(bookDaoClass); bookDao = (BookDao) clazz.getDeclaredConstructor().newInstance(); } catch (Throwable e) { throw new ExceptionInInitializerError(e); } } public static DaoFactory getInstance() { return instance; } public BookDao getBookDao() { return bookDao; } }
相关配置文件
bookDaoClass=com.wise.tiger.dao.impl.BookDaoImpl
数据源配置文件
driverClassName = com.mysql.cj.jdbc.Driver url = jdbc:mysql:///db_book username = root password = ########## 连接池配置 ############# initialSize = 5 maxTotal = 20 maxIdle = 10 minIdle = 3 maxWaitMillis = 1000 connectionProperties = serverTimezone=UTC;useSSL=false;useUnicode=true;characterEncoding=utf-8 # 配置事务是否自动提交 # defaultAutoCommit = false # 配置事务的格力级别 (READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE) # defaultTransactionIsolation = REPEATABLE_READ
短字符指令集(枚举)
package com.wise.tiger.commons; import java.util.HashMap; import java.util.Map; public enum CommandLineInput { FIND_ALL('a'), FIND_BY_ID('f'), INSERT('i'), UPDATE('u'), DELETE('d'), EXIT('e'); private final static Map<Character, CommandLineInput> INPUTS; static { INPUTS = new HashMap<>(); for (CommandLineInput input : values()) { INPUTS.put(input.getShortCmd(), input); } } private final char shortCmd; CommandLineInput(char shortCmd) { this.shortCmd = shortCmd; } public char getShortCmd() { return shortCmd; } public static CommandLineInput getCommandLineInputForInput(char input) { return INPUTS.get(input); } }
工具类
package com.wise.tiger.commons; // ****************** import ******************// public class CommandLineInputHandler { private BookService service = new BookServiceImplInDB(); public void printOptions() { System.out.println("\n--- Book Application ---"); System.out.println("Please make a choice:"); System.out.println("(a)ll items"); System.out.println("(f)ind a specific item"); System.out.println("(i)nsert a new item"); System.out.println("(u)pdate an existing item"); System.out.println("(d)elete an existing item"); System.out.println("(e)xit"); } public String readInput() { Scanner scanner = new Scanner(System.in); return scanner.nextLine(); } public void processInput(CommandLineInput input) { if (input == null) { handleUnknownInput(); } else { switch (input) { case FIND_ALL: printAllBookItems(); break; case FIND_BY_ID: printBookItem(); break; case INSERT: insertToDoItem(); break; case UPDATE: updateToDoItem(); break; case DELETE: deleteToDoItem(); break; case EXIT: break; default: handleUnknownInput(); } } } private Integer askForItemId() { System.out.println("Please enter the book ID:"); String input = readInput(); return Integer.parseInt(input); } private Book askForNewToDoAction() { var book = new Book(); System.out.println("Please enter the title of the book:"); book.setTitle(readInput()); System.out.println("Please enter the author of the book:"); book.setAuthor(readInput()); System.out.println("Please enter the price of the book:"); book.setPrice(Float.parseFloat(readInput())); System.out.println("Please enter the publisher of the book:"); book.setPublisher(readInput()); System.out.println("Please enter the intro of the book:"); book.setIntro(readInput()); return book; } private void printAllBookItems() { var books = service.search(); if (books.isEmpty()) { System.out.println("没有图书,赶快去添加一本吧!"); } else { for (var book : books) System.out.println(book); } } private void printBookItem() { var book = findBookItem(); if (book != null) { System.out.println(book); } } private Book findBookItem() { Integer id = askForItemId(); var book = service.search(id); if (book == null) System.err.println("book item with ID " + id + " could not be found."); return book; } private void insertToDoItem() { var book = askForNewToDoAction(); service.save(book); System.out.println("Successfully inserted book item ."); } private void updateToDoItem() { var book = findBookItem(); if (book != null) { System.out.println(book); System.out.println("Please enter the title of the book:"); book.setTitle(readInput()); System.out.println("Please enter the author of the book:"); book.setAuthor(readInput()); System.out.println("Please enter the price of the book:"); book.setPrice(Float.parseFloat(readInput())); System.out.println("Please enter the publisher of the book:"); book.setPublisher(readInput()); System.out.println("Please enter the intro of the book:"); book.setIntro(readInput()); service.merge(book); System.out.println("Successfully updated book item with ID " + book.getId() + "."); } } private void deleteToDoItem() { var book = findBookItem(); if (book != null) { service.remove(book.getId()); System.out.println("Successfully deleted book item with ID " + book.getId() + "."); } } private void handleUnknownInput() { System.out.println("Please select a valid option!"); } }
DBHelper工具类,用于获取连接等(后续添加事务控制)
package com.wise.tiger.commons; // ****************** import ******************// public class DBHelper { private static DataSource dataSource; private DBHelper(){ } static { try { var prop = new Properties(); prop.load(DBHelper.class.getClassLoader().getResourceAsStream("dbcp-config.properties")); dataSource = BasicDataSourceFactory.createDataSource(prop); } catch (Exception e) { e.printStackTrace(); } } /** * 获取数据库连接对象 * @return Connection * @throws SQLException 获取连接失败异常 */ public static Connection getConnection() throws SQLException{ try { return dataSource.getConnection(); } catch (SQLException e) { throw e; } } /** * 返回数据源DataSource * @return DataSource */ public static DataSource getDataSource() { return dataSource; } }
程序入口
package com.wise.tiger.client; //************ import ********************/ /** * 程序入口 */ public class BookApp { public static final char DEFAULT_INPUT = '\u0000'; public static void main(String args[]) { CommandLineInputHandler commandLineInputHandler = new CommandLineInputHandler(); char command = DEFAULT_INPUT; while (CommandLineInput.EXIT.getShortCmd() != command) { commandLineInputHandler.printOptions(); String input = commandLineInputHandler.readInput(); char[] inputChars = input.length() == 1 ? input.toCharArray() : new char[]{DEFAULT_INPUT}; command = inputChars[0]; CommandLineInput commandLineInput = CommandLineInput.getCommandLineInputForInput(command); commandLineInputHandler.processInput(commandLineInput); } } }
在该应用中省略了service层,后续事务控制中再进行添加。
至此,一个DAO设计模式就基本完成,但是这里面存在一个问题,就是大量的重复操作以及重复代码,这样的代码不便于我们阅读以及维护,或者由于开发者本身的疏忽而造成sql代码失控,如何解决这一问题呢?在下一节中我们采用模板方法模式以及策略模式对dao加以完善
相关推荐
基于JSP+Servlet+JavaBean+JDBC+DAO的Web架构设计该系统,进一步了解并掌握如何对数据库进行操作,以及如何分析、设计一个应用系统。 需求要求: 该系统的基本需求是,系统要实现如下的基本管理功能: (1)用户分为...
DAO模式是一种软件设计模式,它的主要目的是为了提供一个接口,通过这个接口,应用层可以与数据库进行交互,而无需知道具体的数据库访问细节。DAO接口定义了各种数据库操作方法,如查询、插入、更新和删除。 2. **...
在DAO模式中,JDBC常作为底层实现,负责执行SQL语句。 以下是一些关于DAO操作和JDBC的关键知识点: 1. **连接数据库**:使用`java.sql.DriverManager`类的`getConnection()`方法建立数据库连接。需要提供数据库...
【JDBC 结构优化3 图书管理源码】是一份基于Java编程语言的图书管理系统源代码,它展示了如何使用JDBC(Java Database Connectivity)技术进行数据库操作和结构优化。在这个项目中,开发者可能关注的重点包括数据库...
总的来说,这个基于JSP+JAVABEAN+JDBC的图书管理系统,通过合理地组织前后端交互,实现了对图书数据的有效管理。这种架构模式在早期Web开发中较为常见,它既能够满足基本的功能需求,又具有一定的扩展性和可维护性。...
使用Spring实现DAO模式 在软件开发领域,设计模式是一种被广泛接受的解决特定问题的方案。其中,DAO(Data Access Object)模式旨在提供一种抽象的数据访问机制,将数据访问的逻辑封装在一个对象中,从而使得应用...
- **DAO实现类**:实现`NoteDAO`接口的具体方法,比如`NoteJDBCDAO`,使用JDBC(Java Database Connectivity)来执行SQL语句,完成对数据库的实际操作。 ### 技术栈与功能模块 1. **Servlet与JSP**:作为服务器端...
【基于JDBC-图书管理系统】是一个使用Java编程语言开发的Web应用程序,旨在管理图书信息。该系统采用DAO(数据访问对象)模式与Servlet技术来构建MVC(模型-视图-控制器)架构,实现了对数据库的基本操作,包括增、...
【初学者第一个小项目基于JDBC+Oracle实现图书管理系统】是一个经典的编程实践,它涵盖了数据库操作、面向对象设计以及简单的用户交互。在这个项目中,我们将深入理解如何利用Java的JDBC(Java Database ...
通过阅读和理解这些代码,初学者可以深入理解Java DAO模式以及如何在实际项目中应用。同时,这也是一个很好的实践机会,可以学习到如何处理数据库操作、异常处理、以及如何组织和设计面向对象的代码结构。对于初学者...
基于JSP+JAVABEAN+JDBC图书管理系统 摘 要 .........................................................1 目 录 .........................................................2 第一章 绪论 ..................
《图书管理系统》是一款基于Web的软件应用,主要利用jsp、servlet、javabean和DAO设计模式构建。本文将深入探讨这些技术以及它们在图书管理系统中的应用。 首先,JSP(JavaServer Pages)是Java技术的一种,用于...
1.需要完成的任务 :开发“图书管理系统”: 技术实现:基于(JSP+Servlet+JavaBean+DAO+JDBC)的Web架构设计该系统。 2.技能训练 (1)掌握web架构设计模式 (2)掌握MVC开发模式; (3)掌握如何编写JavaBean; (4...
DAO模式提供了一种将业务逻辑与数据操作分离的方法,增强了代码的可测试性和可维护性。在图书管理系统中,DAO类封装了SQL语句,实现了对图书数据的操作。 六、业务逻辑层(Service) 业务逻辑层处理系统的核心业务...
通过使用HTML、CSS、JavaScript、JSP、Servlet、JavaBean、JDBC以及DAO等技术,我们可以创建一个功能完备、用户友好的在线图书管理系统。 1. HTML、CSS与JavaScript:作为前端基础,HTML负责页面结构,CSS负责样式...
在图书管理系统中,使用JDBC建立与MySQL的连接,执行SQL语句,并处理结果集。 7. **session和cookie**:为了保持用户登录状态,系统可能使用session或cookie。session在服务器端存储用户信息,cookie则在客户端存储...
在实际项目中,通常会使用DAO(Data Access Object)设计模式,创建专门的数据库操作类,封装JDBC操作,使得业务逻辑与数据访问层分离,提高代码的可复用性和可维护性。此外,为了更好地管理数据库连接,可能还会...
5. **数据访问对象(DAO)模式**:为了更好地分离业务逻辑和数据访问,通常使用DAO模式。DAO是Java对象,它们封装了对数据库的操作,使得业务层代码不直接与数据库API交互,提高代码可读性和可维护性。 6. **模型-...