JDBC的进化2

好了,换了个新屏幕,原来的电脑屏幕,过年的时候擦玻璃,玻璃掉下来给砸的裂开了(玻璃一点事情都没有),新屏幕感觉就是爽,也不枉我花了280大洋买的LG的完美屏。战斗力立马感觉飙升20%。闲话就不多说了,继续进化JDBC。

将JDBC的连接完成后,我们要做什么呢?增删改查呗!

好,那就先来一个原始的起源,然后我们逐渐进化。

1.JDBC的进化2—增删改查

获取连接对象后,我们是这样想的,我们要将我们的sql语句通过这个连接发送到数据库,然后让数据库将结果返回给我们。

通过查看API,发现了Connection接口中createStatement() 这个方法,具体的作用呢,“Creates a Statement object for sending SQL statements to the database.”创建一个Statement对象能发送SQL命令到数据库中,这个方法返回一个Statement对象。好了,可以将sql statement发送到数据库中了,我们想的的执行,然后就结果返回给我们。继续查看API, Statement接口中execute(String sql) ,executeQuery(String sql) ,executeUpdate(String sql) 有这么三个方法参数都是String 的sql。好了就要它了。先来试试第一个execute(String sql)

@Test
    public void testJdbcInsert() throws Exception{
        Connection conn = JDBCUtils.getConnection();
        Statement statm = conn.createStatement();
        String sql = "insert into customers values(21, ‘yushen1‘, ‘[email protected]‘, ‘1998-3-2‘, null)";
        boolean b = statm.execute(sql);
        System.out.println(b);

        statm.close();
        conn.close();
    }

我将异常抛出去了,当然这里不是很合理,但是这都是不重点。重点是执行成功了(通过查看数据库发现的确插入了),但是这里的返回值是false,咦,不合理啊,明明成功了,怎么会是false?查看API,别的不看,我们直接看它的返回值,“true if the first result is a ResultSet object; false if it is an update count or there are no results ”,原来如此,如果是结果是一个ResultSet对象它就返回true,如果是没有结果集或是一个count,返回false。联系学过的sql,我们知道select查询后的结果是一张数据表,而别的DML操作后,仅仅是对表进行了修改,得到的是一个类似这样的结果“1 row(s) affected”。而这时候问题就来了,我们怎么知道得到的一个结果集还是一个count,这样就不利于后续的操作了。进化吧!

2.JDBC的进化2—增删改

2.1JDBC的进化2—增删改1

原始的问题我们已经明白了,我们的解决办法就是将修改(增删改)操作和查询操作分开,看看上面的三个方法,秒懂了,是不是。先来处理简单的,修改,因为它的返回值是一个受影响的行数,我们通过判断这个行数是否为0,就能判断修改是否执行成功。

// update
    @Test
    public void testJdbcUpdate(){
        Connection conn = null;
        Statement statm = null;
        try {
            conn = JDBCUtils.getConnection();
            statm = conn.createStatement();
            String sql = "update customers set name = ‘woshiyushen‘ where id = 21";
            int rows = statm.executeUpdate(sql);
            if( rows > 0){
                System.out.println("success!");
            } else {
                System.out.println("failed");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(statm, conn);
        }

    }

暂且我们将修改进化到这里,后续将其进化。将其封装成一个方法,放到我的工具类中。

// statement : insert,update,delete
    public static int update(String sql) {
        Connection conn = null;
        Statement statm = null;
        int rows = 0;
        try {
            conn = getConnection();
            statm = conn.createStatement();
            rows = statm.executeUpdate(sql);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(statm, conn);
        }
        return rows;
    }

3.JDBC的进化2—查(重点)

3.JDBC的进化2—查1

先来查一个

@Test
    public void testOrderSelect1() {

        // get connection
        Connection conn = null;
        // create Statement object
        Statement statm = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtils.getConnection();
            statm = conn.createStatement();
            // executeQuery, and return a ResultSet object
            String sql = "select order_id, order_name, order_date from `order`";
            rs = statm.executeQuery(sql);

            // read the rs
            while (rs.next()) {
                int orderId = rs.getInt("order_id");
                String orderName = rs.getString("order_name");
                Date orderDate = rs.getDate("order_date");
                // put the resultset to a class
                Order order = new Order(orderId, orderName, orderDate);
                System.out.println(order);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // close conn
            JDBCUtils.close(rs, statm, conn);
        }

    }

我自己英语水平也不是很高,可能存在很多的语法问题,大家将就的看,我也会不断的学习改进。这里直接将结果集的处理也写出来了,这里又涉及到一个思想:ORM(Object Relational Mapping):对象关系映射,拿我自己的话来理解就是,一张表对应一个类,一列对应一个属性,一行对应一个数据,仔细想想,是不是这样的,可能我们一开始想将读出来的数据存到数组,集合中,但是用一个对象来存是不是更好一点?在说说ResultSet,API中是这样说的,“A table of data representing a database result set”包含一个数据库结果集的数据表,得到的是可以认为是一张表,它提供一个光标,通过next()方法,将光标下移,光标所指代表一行。然后我们从这一行中取出数据,存到对象中。

那么问题又来了,这里我们只能针对具体的某一张表,因为你不确定它中列的个数,列的名称。为了提供一种通用的,可移植性高的程序,进化吧!

3.JDBC的进化2—查2

我们想提供一种通用的解决办法,就好比2.1JDBC的进化2—增删改1中我们将其封装成方法,只通过一些参数就能就获取对象。想要获取这个对象,而我们不知道具体是哪个对象,只能在运行时才能确定具体获取什么对象……反射!反射!!!对!那我们来写这个通用的查询方法。

public <T> T get(String sql, Class<T> clazz) {
        T t = null;
        // 1.get the connection
        Connection conn = null;
        // 2.on the base of conn, create Statement object
        Statement statm = null;
        // 3.excute sql command, and get the ResultSet object
        ResultSet rs = null;
        try {
            conn = JDBCUtils.getConnection();
            statm = conn.createStatement();
            rs = statm.executeQuery(sql);
            // get the ResultSetMetaData object
            ResultSetMetaData rsmd = rs.getMetaData();
            // 4.read the data from Result object, and write to a generic object
            while (rs.next()) {
                // 4.1through reflect get the T object t...
                t = clazz.newInstance();
                // 4.2 read the rs‘data to t
                // 4.21 get the columnCount througth the ResultSetMetaData
                int columnCount = rsmd.getColumnCount();
                // 4.22 get the every columnName and columnVal
                for (int i = 1; i <= columnCount; i++) {
                    // 4.23 get the columnName
                    String columnName = rsmd.getColumnLabel(i);
                    // 4.24 get the columnVal from rs
                    Object cloumnVal = rs.getObject(columnName);

                    // 4.25 set the columnName and columnVal to t througth
                    // generic
                    Field field = clazz.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(t, cloumnVal);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 5.close the connection
            JDBCUtils.close(rs, statm, conn);
        }
        // 6. return the t
        return t;
    }

这里需要两个参数,sql就不用多提了,要说的是第二个参数 Class<T> clazz 我们需要通过反射来获取具体类的实例,这里需要我们根据查询的结果建立相应的实体类表,然后通过反射的方式,来为具体的为某个属性赋值。

而得到列数,需要通过ResultSetMetaData才能获取。

到这里的时候,你脑海里是不是会有这样一个层次:



描述类的类(通过反射获取的Class)

描述数据的数据(元数据,如ResultSetMetaData)

思维发散一下:还有一个描述注解的注解(元注解),当然这里没有用到…



往下一个层次:



具体的类

具体的对象

具体的注解



这稍微的进化一下。

3.JDBC的进化2—查3

既然我们说,可以通过属性来为其设置值,我们那么我们也可以同getXXX()和setXXX()为属性赋值。而Apache为我们提供了这样的类库(commons-beanutils-1.8.0.jar,commons-logging-1.1.1.jar,我会随后上传,大家注意看我评论,进行下载使用)。

public <T> List<T> getAll(String sql, Class<T> clazz) {
        List<T> list = new ArrayList<T>();
        Connection conn = null;
        Statement statm = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtils.getConnection();
            statm = conn.createStatement();
            rs = statm.executeQuery(sql);
            ResultSetMetaData rsmd = rs.getMetaData();
            while (rs.next()) {
                T t = clazz.newInstance();
                int cloumnCount = rsmd.getColumnCount();
                for (int i = 1; i <= cloumnCount; i++) {
                    String cloumnName = rsmd.getColumnLabel(i);
                    Object cloumnVal = rs.getObject(cloumnName);
                    PropertyUtils.setProperty(t, cloumnName, cloumnVal);
                }
                list.add(t);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, statm, conn);
        }
        return list;
    }

这里是获取多行,返回多个对象,用List来存放。

做了两个测试:

@Test
    public void test1() {
        String sql = "SELECT order_id orderId, order_name OrderName, order_date orderDate FROM `order` WHERE order_id > 1";
        List<Order> orders = getAll(sql, Order.class);
        for (Order order : orders) {
            System.out.println(order);
        }
    }

    @Test
    public void test() {
        String sql = "SELECT order_id orderId, order_name OrderName, order_date orderDate FROM `order` WHERE order_id = 1";
        Order order = get(sql, Order.class);
        System.out.println(order);
    }

提醒一下,别名的使用,数据库和Java程序命名规范可能有所不同,所以为了保证对应的列名和属性名相同,我们就要用到别名。(getColumnLabel() 优先返回别名)

另附一些练习:

1.创立数据库表 examstudent,表结构如下:

2.向数据库表中添加一些数据

3.插入一个新的 student 信息

请输入考生的详细信息

Type:

IDCard:

ExamCard:

StudentName:

Location:

Grade:

信息录入成功!

4.根据输入的身份证号和准考证号来查询学生的基本信息

5.根据考生号删除学生

ok,今天就进化到这里吧。明天继续。LG的屏的确挺不错的!

时间: 2024-10-07 20:02:20

JDBC的进化2的相关文章

JDBC的进化3

这次进化完成后,JDBC的进化就需要设置一个savepoint了,然后提交一下,提交到我们的脑袋硬盘中. 上一次说到了利用Statement对象来发送sql语句到数据库.然而这样的话,会暴露出两个问题. 那么问题来了!!! 问题1: 在执行executeUpdate(String sql)和executeQuery(String sql)方法时,我们需要拼写sql字符串,就像下面这样: String sql = "insert into customers values(21, 'yushen1

JDBC的进化3--补充:事务处理

接着JDBC的进化3,我们来说数据库事务. 事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态. 怎么理解呢? 一组逻辑单元:我认为指的是多条的DML操作,只是一条DML语句的话,对于mysql来说,执行完成功就自动提交了,没成功的话,就没成功喽,这样说来,一条DML语句就相当于一个原子,不可再分了. 从一种状态变换到另一种状态:即这组操作是成功了还是失败了,他们必须同时都成功,有一个失败,就退回到起点.例如银行的转账,不能一个成功,一个失败吧. 来看看JDBC的事务处理: 先来看看,在什

JDBC的进化

1.数据的存储方式的进化 ①字符串 ②数组 ③文件 ④数据库 其中①和②是存在内存中,会随着程序的终止而结束,不会保留到本地磁盘 ③和④则会将数据存储到本地磁盘,而④可以对数据进行管理,可以根据不同的应用场景选择不同量级的数据库 2.JDBC的进化 起源: Java程序要对磁盘中的数据进行读写,各大数据库厂商提供了相应的驱动,Java提供了相应的接口进行连接. 进化1:面向对象编程 @Test public void testOrclJdbc1() throws SQLException { D

JDBC的进化4--最终进化

除去直接调用开源组织给提供的jar包外,我今天要说的内容就是JDBC的最终版,需要我们多敲多练多理解.最重要的是理解.废话不多说了,开始吧. 早上的时候,我将昨天的内容整理,能处理事务的通用方法写到了JDBCUtils工具类中. 其实到这里的时候,所有细节部分的代码都已经实现了.接下来要进行的内容,其实就是对这些内容的整合,整体的调控. 我们来说DAO: 现在我们希望这个程序能更加自动化一点,我们只需要提供一个连接,它就能返回给我们一个对象或一个对象集,或一个结果.或是我们提供一个连接,一个对象

JavaSE:集合总结(Collection,Map)

今天来总结JavaSE部分的集合.首先来从整体来看: 我们主要要学习的内容: Collection: Collection(接口): java.util.Collection |-- List(子接口) : |--ArrayList |--LinkedList |--Vector |-- Set(子接口) : |--AbstracSet(子接口) |--HashSet |--LinkedHashSet |--SortedSet(子接口) |--TreeSet |-- Queue(子接口) : M

Spring DAO vs Spring ORM vs Spring JDBC

Pat 的疑惑 最近关注于 Spring 提供的数据访问技术,对于 Spring 相关的这几个项目有何不同我不是太明白: Spring-DAO (http://docs.spring.io/spring/docs/2.0.8/reference/dao.html) Spring-ORM (http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/orm.html) Spring-JDBC (http://doc

jdbc的简单使用

1.加载驱动(mysql的驱动是com.mysql.jdbc.Driver,SqlServer的驱动是 com.microsoft.sqlserver.jdbc.SQLServerDriver) 2.加载数据库的连接(url, username,password) 3.编写sql语句(String sql="select * from grade  where gradeName = ?";) 4.遍历查询结果 [while (resultSet.next()) {   System.

商城项目整理(三)JDBC增删改查

商品表的增加,修改,删除,订单表的增加,确认,用户表的查看,日志表的增加,查看 商品表建表语句: 1 create table TEST.GOODS_TABLE 2 ( 3 gid NUMBER not null, 4 gname VARCHAR2(90), 5 gdetails CLOB, 6 gpicture VARCHAR2(100), 7 gprice NUMBER, 8 gleixing NUMBER, 9 gpinpai VARCHAR2(20) 10 ) 11 tablespace

jdbc驱动jar导入eclipse

在使用JDBC编程时需要连接数据库,导入JAR包是必须的,导入其它的jar包方法同样如此,导入的方法是 打开eclipse 1.右击要导入jar包的项目,点properties 2.左边选择java build path,右边选择libraries 3.选择add External jars 4.选择jar包的按照路径下的确定后就行了. Java连接MySQL的最新驱动包下载地址 http://www.mysql.com/downloads/connector/j 有两种方法导入jar包,第一种