什么是 DAO
DAO(Data Access Object)是一个数据访问接口,夹在业务逻辑与数据库资源中间。
在核心J2EE模式中是这样介绍DAO模式的:为了建立一个健壮的J2EE应用,应该将所有对数据源的访问操作抽象封装在一个公共API中。用程序设计的语言来说,就是建立一个接口,接口中定义了此应用程序中将会用到的所有事务方法。在这个应用程序中,当需要和数据源进行交互的时候则使用这个接口,并且编写一个单独的类来实现这个接口在逻辑上对应这个特定的数据存储。DAO中的主要操作:增删改查(CRUD).
DAO的实现
实现的步骤一般是:
- 先建立模型的对象domain
- 编写DAO接口
- 定义DAO实现类
- 生产DAO测试类
- 在DAO测试类中测试方法
一般的规范是分domain包和dao包,dao包中有DAO接口,接口名为IXxxDAO,实现类为XxxDAO,创建实现类对象赋给接口,体现多态。还有一个测试类名为XxxTestDAOTest.如:
DAO接口:
public interface IStudentDAO {
/**
* 保存学生对象
* @param stu 需要保存的学生
*/
void save(Student stu);
/**
* 删除指定id的学生
* @param id 需要删除的学生的id
*/
void delete(int id);
/**
* 更改操作
* @param newStu 更改后的学生对象,根据id更改
*/
void update(Student newStu);
/**
* 根据id查询单个学生对象信息
* @param id 需要查询学生的id
* @return 存在该学生返回学生对象 不存在则返回null
*/
Student get(long id );
/**
* 查询所有学生
* @return 返回一个学生对象的集合
*/
List<Student> list();
}
public interface IStudentDAO {
/**
* 保存学生对象
* @param stu 需要保存的学生
*/
void save(Student stu);
/**
* 删除指定id的学生
* @param id 需要删除的学生的id
*/
void delete(int id);
/**
* 更改操作
* @param newStu 更改后的学生对象,根据id更改
*/
void update(Student newStu);
/**
* 根据id查询单个学生对象信息
* @param id 需要查询学生的id
* @return 存在该学生返回学生对象 不存在则返回null
*/
Student get(long id );
/**
* 查询所有学生
* @return 返回一个学生对象的集合
*/
List<Student> list();
}
实现类:
public void save(Student stu) {
String sql = "INSERT INTO s_student(name,age) VALUES('狗哲',21)";
Connection conn = null;
Statement st = null
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///demo","root","admin");
st = conn.createStatement();
st.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
}finally {
try{
if(st != null){
st.close();
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(conn != null){
conn.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
增删改只有sql语句不一样,省略
····
····
public List<Student> list() {
String sql = "SELECT * FROM s_student";
Connection conn = null;
Statement st = null;
ResultSet rs = null;
List<Student> list = new ArrayList<>();
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///demo","root","admin");
st = conn.createStatement();
rs = st.executeQuery(sql);
while(rs.next()){
String name = rs.getString("name");
Integer age = rs.getInt("age");
list.add(new Student(name,age));
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try{
if(st != null){
st.close();
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(conn != null){
conn.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
return list;
}
public void save(Student stu) {
String sql = "INSERT INTO s_student(name,age) VALUES('狗哲',21)";
Connection conn = null;
Statement st = null
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///demo","root","admin");
st = conn.createStatement();
st.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
}finally {
try{
if(st != null){
st.close();
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(conn != null){
conn.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
增删改只有sql语句不一样,省略
····
····
public List<Student> list() {
String sql = "SELECT * FROM s_student";
Connection conn = null;
Statement st = null;
ResultSet rs = null;
List<Student> list = new ArrayList<>();
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///demo","root","admin");
st = conn.createStatement();
rs = st.executeQuery(sql);
while(rs.next()){
String name = rs.getString("name");
Integer age = rs.getInt("age");
list.add(new Student(name,age));
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try{
if(st != null){
st.close();
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(conn != null){
conn.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
return list;
}
DAO实现的重构
可以看出代码重复非常之多,尤其是增删改只有sql语句不一样
- 1、定义一个JdbcUtil类,把加载注册驱动放到静态代码块中,因为没有必要每次都去加载。
- 2、把url,classDriverName,username,password ,放在一个资源文件中,用加载资源文件的方式获取这些值,保证了代码的可维护性
- 3、异常处理代码也放在工具类中,异常处理及其麻烦,影响代码的美观
public class JdbcUtil {
private static Properties p = new Properties();
//加载资源文件
static{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream inStream = loader.getResourceAsStream("db.properties");
try {
p.load(inStream);
Class.forName(p.getProperty("classDriver"));
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接对象
public static Connection getConn(){
Connection conn = null;
try {
conn = DriverManager.getConnection(p.getProperty("url"),p.getProperty("username"), p.getProperty("password"));
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
//关闭资源
public static void close(Connection conn,Statement st,ResultSet rs){
try{
if(rs != null){
rs.close();
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(st != null){
st.close();
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
public class JdbcUtil {
private static Properties p = new Properties();
//加载资源文件
static{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream inStream = loader.getResourceAsStream("db.properties");
try {
p.load(inStream);
Class.forName(p.getProperty("classDriver"));
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接对象
public static Connection getConn(){
Connection conn = null;
try {
conn = DriverManager.getConnection(p.getProperty("url"),p.getProperty("username"), p.getProperty("password"));
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
//关闭资源
public static void close(Connection conn,Statement st,ResultSet rs){
try{
if(rs != null){
rs.close();
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(st != null){
st.close();
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}