JDBC+反射教你手写自己的Dao层框架

大家好,我是一个爱举铁的程序员Shr。

本篇文章将用到前几篇文章介绍过的知识自定义数据访问层框架,建议看这篇文章之前先去了解JDBC元数据和反射。

如果是初学者,觉得JDBC封装数据太麻烦,一个类十多个字段,重复的代码导致浪费了大量时间,那待会我开车的时候你可要抓紧了。

如果你用Hibernate,Mybatis用了两三年还只是停留在使用的情况,看源码太费劲,看一会就想睡觉,本篇文章将带你走进框架底层,探索精彩的世界。

本篇文章较长,耐心看完~~~

源码地址:https://github.com/ShrMus/Dao/tree/master/dao_20180603/src/main/java/com/shrmus/jdbc02

一、新建数据库表

新建名为dao_20180603的数据库,再新建emp表

CREATE TABLE `emp` (
  `id` int(11) NOT NULL,
  `name` varchar(255) default NULL,
  `address` varchar(255) default NULL,
  `hireDate` datetime default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

二、新建类

public class Emp {
    private int id;
    private String name;
    private String address;
    private Date hireDate;
    public Emp() {
    }
    public Emp(int id, String name, String address, Date hireDate) {
        this.id = id;
        this.name = name;
        this.address = address;
        this.hireDate = hireDate;
    }
    @Override
    public String toString() {
        return "Emp [id=" + id + ", name=" + name + ", address=" + address + ", hireDate=" + hireDate + "]";
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public Date getHireDate() {
        return hireDate;
    }
    public void setHireDate(Date hireDate) {
        this.hireDate = hireDate;
    }
}

三、新建数据源类

/**
 * 自定义数据源
 * <p>Title:MyDataSource</p>
 * <p>Description:</p>
 * @author Shr
 * @date 2018年6月3日上午9:32:51
 * @version
 */
public class MyDataSource {
    // 数据库驱动
    private final String driverClassName;
    // 数据库连接URL
    private final String url;
    // 数据库用户名
    private final String username;
    // 数据库密码
    private final String password;
    /**
     * 构造方法注入属性值
     */
    public MyDataSource(){
        Properties properties = new Properties();
        InputStream inputStream;
        try {
            String path = this.getClass().getResource("").getPath();
            inputStream = new FileInputStream(path + "/jdbc.properties");
            properties.load(inputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.driverClassName = properties.getProperty("jdbc.driverClassName");
        this.url = properties.getProperty("jdbc.url");
        this.username = properties.getProperty("jdbc.username");
        this.password = properties.getProperty("jdbc.password");
    }
    public MyDataSource(String driverClassName,String url,String username,String password){
        this.driverClassName = driverClassName;
        this.url = url;
        this.username = username;
        this.password = password;
    }
    public String getDriverClassName() {
        return driverClassName;
    }
    public String getUrl() {
        return url;
    }
    public String getUsername() {
        return username;
    }
    public String getPassword() {
        return password;
    }
}

四、新建数据库连接属性文件

新建文件jdbc.properties,文件和数据源类在同一个目录,文件内容如下:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/dao_20180603?characterEncoding=utf8
jdbc.username=root
jdbc.password=shrmus

五、新建数据库连接类

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
 * 自定义连接
 * <p>Title:MyConnection</p>
 * <p>Description:</p>
 * @author Shr
 * @date 2018年6月3日上午9:59:31
 * @version
 */
public final class MyConnection{
    private Connection connection = null;
    public MyConnection() {
    }
    public MyConnection(MyDataSource myDataSource) {
        try {
            Class.forName(myDataSource.getDriverClassName());
            connection = DriverManager.getConnection(myDataSource.getUrl(), myDataSource.getUsername(), myDataSource.getPassword());
        } catch (ClassNotFoundException e) {
            System.err.println("构造MyConnection实例失败!");
        } catch (SQLException e) {
            System.err.println("获取MyConnection失败!");
        }
    }
    public Connection getConnection() {
        return connection;
    }
    /**
     * 关闭数据库连接对象
     * @param connection
     */
    public static void close(Connection connection) {
        if(null != connection) {
            try {
                connection.close();
            } catch (SQLException e) {
                System.err.println("关闭数据库连接对象失败!");
            }
        }
    }
    /**
     * 关闭SQL执行对象
     * @param statement
     */
    public static void close(Statement statement) {
        if(null != statement) {
            try {
                statement.close();
            } catch (SQLException e) {
                System.err.println("关闭SQL执行对象失败!");
            }
        }
    }
    /**
     * 关闭结果集对象
     * @param resultSet
     */
    public static void close(ResultSet resultSet) {
        if(null != resultSet) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                System.err.println("关闭结果集对象失败!");
            }
        }
    }
    /**
     * 关闭数据库连接对象,SQL执行对象,结果集对象
     * @param resultSet
     * @param statement
     * @param connection
     */
    public static void close(ResultSet resultSet, Statement statement, Connection connection){
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                System.err.println("关闭结果集对象失败!");
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                System.err.println("关闭SQL执行对象失败!");
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                System.err.println("关闭数据库连接对象失败!");
            }
        }
    }
}

六、新建查询类

这个类用来对数据进行增删改查。

/**
 * 自定义SQL执行对象
 * <p>Title:MyQuery</p>
 * <p>Description:</p>
 * @author Shr
 * @date 2018年6月3日上午10:18:11
 * @version
 */
public class MyQuery {
    // 数据库连接对象
    public Connection connection;
    public MyQuery() {
        MyDataSource myDataSource = new MyDataSource();
        MyConnection myConnection = new MyConnection(myDataSource);
        this.connection = myConnection.getConnection();
    }
    public MyQuery(MyDataSource myDataSource) {
        MyConnection myConnection = new MyConnection(myDataSource);
        this.connection = myConnection.getConnection();
    }
}

七、测试

看到这里,你已经发现和原先的JDBCUtil完全不一样了,为什么要这么做呢,为了做到功能单一。

后面关键的地方来了。

7.1 测试添加员工

7.1.1 在查询类中添加代码

    /**
     * 插入一条记录
     * @param object
     */
    public void insert(Object object) {
        PreparedStatement prepareStatement = null;
        ResultSet resultSet = null;
        Class<? extends Object> clazz = object.getClass();
        // 获取简单类名,数据库表名和类名一致
        String simpleName = clazz.getSimpleName();
        // 获取字段
        Field[] declaredFields = clazz.getDeclaredFields();
        String sql = "insert into " + simpleName;
        String fieldString = "(";
        String valueString = "values(";
        // 获取字段的个数
        int length = declaredFields.length;
        try {
            for(int i = 0; i < length - 1; i++) {
                // 私有字段设置允许访问
                declaredFields[i].setAccessible(true);
                // 获取字段值
                Object fieldValue = declaredFields[i].get(object);
                String typeName = declaredFields[i].getGenericType().getTypeName();
                if(typeName.toLowerCase().contains("date")) {
                    // 如果是日期类型
                    Date date = (Date) fieldValue;
                    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String format = dateFormat.format(date);
                    fieldValue = format;
                }
                // 拼接字段名
                fieldString += declaredFields[i].getName() + ",";
                // 拼接字段值
                valueString += "'" + fieldValue + "',";
            }
            declaredFields[length - 1].setAccessible(true);
            // 获取字段值
            Object fieldValue = declaredFields[length - 1].get(object);
            // 获取字段类型名称
            String typeName = declaredFields[length - 1].getGenericType().getTypeName();
            if(typeName.toLowerCase().contains("date")) {
                // 如果是日期类型
                Date date = (Date) fieldValue;
                DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String format = dateFormat.format(date);
                fieldValue = format;
            }
            // 拼接字段名
            fieldString += declaredFields[length - 1].getName() + ") ";
            // 拼接字段值
            valueString += "'" + fieldValue + "')";
            // 拼接SQL语句
            sql = sql + fieldString + valueString;
            System.out.println("SQL = " + sql);
            // 设置事务手动提交
            this.connection.setAutoCommit(false);
            prepareStatement = this.connection.prepareStatement(sql);
            prepareStatement.executeUpdate();
            // 提交事务
            this.connection.commit();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            try {
                // 回滚事务
                this.connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            // 关闭连接
            MyConnection.close(resultSet, prepareStatement, connection);
        }
    }

7.1.2 编写Dao类

public class EmpDao {
    /**
     * 添加员工的信息
     */
    public void insert(Emp emp) {
        MyQuery myQuery = new MyQuery();
        myQuery.insert(emp);
    }
}

7.1.3 编写测试类

public class EmpTest {
    /**
     * 测试添加
     */
    @Test
    public void inser() throws Exception{
        Emp emp = new Emp(2,"李四","株洲",new Date());
        EmpDao empDao = new EmpDao();
        empDao.insert(emp);
    }
}

运行结果:

SQL = insert into Emp(id,name,address,hireDate) values('1','张三','长沙','2018-06-03 23:49:12')

再看数据库:

添加了一条数据。查询类中的inser()方法根据传过来的参数,获取数据库表的主键,再获取字段和字段值,方法内部拼接SQL语句。

7.2 测试查询所有员工

7.2.1 在查询类中添加代码

    /**
     * 查询所有信息
     * @param t
     * @return
     */
    @SuppressWarnings({ "unchecked", "resource" })
    public <T> List<T> select(Class<T> t){
        PreparedStatement prepareStatement = null;
        ResultSet resultSet = null;
        List<T> objectList = new ArrayList<>();
        // 获取模板T的实例
        T newInstance2 = null;
        try {
            newInstance2 = t.newInstance();
        } catch (InstantiationException | IllegalAccessException e1) {
            e1.printStackTrace();
        }
        T newInstance;
        // 获取实例的Class类对象
        Class<? extends Object> clazz = newInstance2.getClass();
        // 获取简单类名,数据库表名和类名一致
        String simpleName = clazz.getSimpleName();
        try {
            // 获取数据库元数据
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            // 获取表列
            resultSet = databaseMetaData.getColumns(null, null, simpleName, null);
            List<String> columnNameList = new ArrayList<>();
            while(resultSet.next()) {
                // 获取列名
                String columnName = resultSet.getString("COLUMN_NAME");
                columnNameList.add(columnName);
            }
            // 定义SQL语句
            String sql = "select ";
            for(String columnName : columnNameList) {
                sql += columnName + ",";
            }
            // 删除最后一个逗号
            int lastIndexOf = sql.lastIndexOf(",");
            sql = sql.substring(0, lastIndexOf);
            sql += " from " + simpleName;
            System.out.println("SQL = " + sql);
            prepareStatement = this.connection.prepareStatement(sql);
            // 执行查询
            resultSet = prepareStatement.executeQuery();
            while(resultSet.next()) {
                // 创建一个新的实例
                newInstance = (T) clazz.newInstance();
                // 获取结果集元数据
                ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
                // 获取查询出来的总列数
                int columnCount = resultSetMetaData.getColumnCount();
                for(int i = 0; i < columnCount; i++) {
                    // 获取列名
                    String columnName = resultSetMetaData.getColumnName(i + 1);
                    // 获取列值
                    Object fieldValue = resultSet.getObject(columnName);
                    // 根据列名获取字段
                    Field declaredField = clazz.getDeclaredField(columnName);
                    // 私有字段设置允许访问
                    declaredField.setAccessible(true);
                    // 调用方法给字段赋新的值
                    declaredField.set(newInstance, fieldValue);
                }
                objectList.add(newInstance);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            // 关闭连接
            MyConnection.close(resultSet, prepareStatement, connection);
        }
        return objectList;
    }

7.2.2 编写Dao类

    /**
     * 查询所有员工
     */
    public List<Emp> getEmpList() {
        MyQuery myQuery = new MyQuery();
        List<Emp> select = myQuery.select(Emp.class);
        return select;
    }

7.2.3 编写测试类

    /**
     * 测试查询所有员工
     */
    @Test
    public void getEmpList() throws Exception {
        EmpDao empDao = new EmpDao();
        List<Emp> empList = empDao.getEmpList();
        for(Emp emp : empList) {
            System.out.println(emp);
        }
    }

在运行这个测试方法之前我又添加了一条数据。

运行结果:

SQL = select id,name,address,hireDate from Emp

Emp [id=1, name=张三, address=长沙, hireDate=2018-06-03 23:49:12.0]

Emp [id=2, name=李四, address=株洲, hireDate=2018-06-04 00:00:18.0]

7.3 测试根据主键查询员工

7.3.1 在查询类添加代码

    /**
     * 根据主键查询
     * @param t
     * @return
     */
    @SuppressWarnings({ "unchecked", "resource" })
    public <T> T selectByPrimaryKey(T t){
        PreparedStatement prepareStatement = null;
        ResultSet resultSet = null;
        Class<? extends Object> clazz = t.getClass();
        // 获取简单类名,数据库表名和类名一致
        String simpleName = clazz.getSimpleName();
        T newInstance = null;
        try {
            // 创建一个新的实例
            newInstance = (T) clazz.newInstance();
            // 获取数据库元数据
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            // 获取给定表主键列的描述
            resultSet = databaseMetaData.getPrimaryKeys(null, null, simpleName);
            String primaryKey = null;
            if(resultSet.next()) {
                // 获取主键列的名称
                primaryKey = resultSet.getString("COLUMN_NAME");
            }
            // 获取表列
            resultSet = databaseMetaData.getColumns(null, null, simpleName, null);
            List<String> columnNameList = new ArrayList<>();
            while(resultSet.next()) {
                // 获取列名
                String columnName = resultSet.getString("COLUMN_NAME");
                columnNameList.add(columnName);
            }
            if(null != primaryKey) {
                // 获取主键在实体类中的同名字段
                Field declaredField = clazz.getDeclaredField(primaryKey);
                // 设置私有字段允许访问
                declaredField.setAccessible(true);
                // 获取字段的值
                Object primaryKeyValue = declaredField.get(t);
                // 获取所有字段
                Field[] declaredFields = clazz.getDeclaredFields();
                // 定义SQL语句
                String sql = "select ";
                for(String columnName : columnNameList) {
                    sql += columnName + ",";
                }
                // 删除最后一个逗号
                int lastIndexOf = sql.lastIndexOf(",");
                sql = sql.substring(0, lastIndexOf);
                sql += " from " + simpleName + " where " + primaryKey + "='" + primaryKeyValue + "'";
                System.out.println("SQL = " + sql);
                prepareStatement = connection.prepareStatement(sql);
                resultSet = prepareStatement.executeQuery();
                if(resultSet.next()) {
                    // 获取结果集元数据
                    ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
                    // 获取查找出来的总列数
                    int columnCount = resultSetMetaData.getColumnCount();
                    for (int i = 0; i < columnCount; i++) {
                        // 获取列名
                        String columnName = resultSetMetaData.getColumnName(i + 1);
                        // 获取列值
                        Object columnValue = resultSet.getObject(columnName);
                        for(Field field : declaredFields) {
                            field.setAccessible(true);
                            // 属性名和字段名一样
                            if(field.getName().equals(columnName)){
                                // 设置属性值
                                field.set(newInstance, columnValue);
                            }
                        }
                    }
                }
            } else {
                System.err.println("主键为空!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } finally {
            MyConnection.close(resultSet, prepareStatement, connection);
        }
        return newInstance;
    }

7.3.2 编写Dao类

    /**
     * 根据主键查询员工的信息
     */
    public Emp selectByPrimaryKey(Emp emp) {
        MyQuery myQuery = new MyQuery();
        emp = myQuery.selectByPrimaryKey(emp);
        return emp;
    }

7.3.3 编写测试类

    /**
     * 测试根据主键查询
     */
    @Test
    public void selectByPrimaryKey() throws Exception {
        EmpDao empDao = new EmpDao();
        Emp emp = new Emp();
        emp.setId(1);
        emp = empDao.selectByPrimaryKey(emp);
        System.out.println(emp);
    }

运行结果:

SQL = select id,name,address,hireDate from Emp where id='1'

Emp [id=1, name=张三, address=长沙, hireDate=2018-06-03 23:49:12.0]

7.4 测试修改员工的信息

7.4.1 编写查询类

    /**
     * 根据主键修改记录
     * @param object
     */
    public void updateByPrimaryKey(Object object) {
        PreparedStatement prepareStatement = null;
        ResultSet resultSet = null;
        Class<? extends Object> clazz = object.getClass();
        // 获取简单类名,数据库表名和类名一致
        String simpleName = clazz.getSimpleName();
        try {
            // 获取数据库元数据
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            // 获取给定表主键列的描述
            resultSet = databaseMetaData.getPrimaryKeys(null, null, simpleName);
            String primaryKey = null;
            if(resultSet.next()) {
                // 获取主键列的名称
                primaryKey = resultSet.getString("COLUMN_NAME");
            }
            if(null != primaryKey) {
                // 获取主键在实体类中的同名字段
                Field declaredField = clazz.getDeclaredField(primaryKey);
                // 设置私有字段允许访问
                declaredField.setAccessible(true);
                // 获取字段的值
                Object primaryKeyValue = declaredField.get(object);
                // 获取字段
                Field[] declaredFields = clazz.getDeclaredFields();
                // 定义SQL语句
                String sql = "update " + simpleName + " set ";
                for(Field field : declaredFields) {
                    String fieldName = field.getName();
                    // 这个字段不是主键
                    if(!fieldName.equals(primaryKey)) {
                        // 设置允许访问
                        field.setAccessible(true);
                        sql += fieldName + "='";
                        // 获取属性值
                        Object fieldValue = field.get(object);
                        // 获取字段类型名称
                        String typeName = field.getGenericType().getTypeName();
                        // 不是基本数据类型
                        if(typeName.toLowerCase().contains("date")) {
                            // 如果是日期类型
                            Date date = (Date) fieldValue;
                            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            String format = dateFormat.format(date);
                            sql += format + "', ";
                        }else {
                            sql += fieldValue + "', ";
                        }
                    }
                }
                // 删除最后一个逗号
                int lastIndexOf = sql.lastIndexOf(",");
                sql = sql.substring(0, lastIndexOf);
                sql += " where " + primaryKey + "='" + primaryKeyValue + "' ";
                System.out.println("SQL = " + sql);
                // 开启事务
                connection.setAutoCommit(false);
                prepareStatement = connection.prepareStatement(sql);
                prepareStatement.executeUpdate();
                // 提交事务
                connection.commit();
            } else {
                System.err.println("主键为空!");
            }
        } catch (SQLException e) {
            try {
                // 事务回滚
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            MyConnection.close(resultSet, prepareStatement, connection);
        }
    }

7.4.2 编写Dao类

    /**
     * 根据主键修改员工的信息
     */
    public void updateByPrimaryKey(Emp emp) {
        MyQuery myQuery = new MyQuery();
        myQuery.updateByPrimaryKey(emp);
    }

7.4.3 编写测试类

    /**
     * 测试修改
     */
    @Test
    public void updateByPrimaryKey() throws Exception {
        Emp emp = new Emp(1,"王五","广州",new Date());
        EmpDao empDao = new EmpDao();
        empDao.updateByPrimaryKey(emp);
    }

运行结果:

SQL = update Emp set name='王五', address='广州', hireDate='2018-06-04 00:05:55' where id='1'

看看数据库:

修改成功了。激动人心吧。以前怎么没发现JDBC元数据这么好使呢。

7.5 测试删除员工

7.5.1 编写查询类

    /**
     * 根据主键删除记录
     * @param object
     */
    public void deleteByPrimaryKey(Object object) {
        PreparedStatement prepareStatement = null;
        ResultSet resultSet = null;
        Class<? extends Object> clazz = object.getClass();
        // 获取简单类名,数据库表名和类名一致
        String simpleName = clazz.getSimpleName();
        try {
            // 获取数据库元数据
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            // 获取给定表主键列的描述
            resultSet = databaseMetaData.getPrimaryKeys(null, null, simpleName);
            String primaryKey = null;
            if(resultSet.next()) {
                // 获取主键列的名称
                primaryKey = resultSet.getString("COLUMN_NAME");
            }
            if(null != primaryKey) {
                // 获取主键在实体类中的同名字段
                Field declaredField = clazz.getDeclaredField(primaryKey);
                // 设置私有字段允许访问
                declaredField.setAccessible(true);
                // 获取字段的值
                Object primaryKeyValue = declaredField.get(object);
                // 定义SQL语句
                String sql = "delete from " + simpleName + " where " + primaryKey + "='" + primaryKeyValue + "'";
                System.out.println("SQL = " + sql);
                // 开启事务
                connection.setAutoCommit(false);
                prepareStatement = connection.prepareStatement(sql);
                prepareStatement.executeUpdate();
                connection.commit();
            } else {
                System.err.println("主键为空!");
            }
        } catch (SQLException e) {
            try {
                // 事务回滚
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            MyConnection.close(resultSet, prepareStatement, connection);
        }
    }

7.5.2 编写Dao类

    /**
     * 根据主键删除员工的信息
     */
    public void deleteByPrimaryKey(Emp emp) {
        MyQuery myQuery = new MyQuery();
        myQuery.deleteByPrimaryKey(emp);
    }

7.5.3 编写测试类

    /**
     * 测试删除
     */
    @Test
    public void deleteByPrimaryKey() throws Exception {
        Emp emp = new Emp(1,"李四","广州",new Date());
        EmpDao empDao = new EmpDao();
        empDao.deleteByPrimaryKey(emp);
    }

运行结果:

SQL = delete from Emp where id='1'

再看看数据库:

因为是根据主键删除的,所以测试类的员工的名字是李四就忽略了。

总结

如果你仔细看了查询类的代码或者你自己有练习过,你就会发现那些框架是怎样的思路了。XML,注解,映射就都能拨云见日了。以前在Dao类作死地封装数据,现在就轻松多了。

注意事项:

我写的都是基本的增删改查,没有涉及到多表查询的。

目前只支持MySQL

只支持表名和类名一样

只支持表中字段和类的属性名一样

不支持联合主键

未预防SQL注入

未提供连接池

关于JDBC元数据和反射的知识点我就不多说了,可能看不懂的也看不到底下了,如果有疑问可以给我留言。

猜你喜欢

转载自blog.csdn.net/ShrMuscles/article/details/80562147