java数据库管理之jdbc

JDBC概念和数据库驱动程序

  • A: JDBC概念和数据库驱动程序
    • a: JDBC概述
      • JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。是Java访问数据库的标准规范
      • JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
      • JDBC需要连接驱动,驱动是两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,
        设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。
      • 我们使用的是mysql的驱动mysql-connector-java-5.1.39-bin.jar
    • b: 总结
      • JDBC是java提供给开发人员的一套操作数据库的接口
      • 数据库驱动就是实现该接口的实现类

JDBC原理

  • a: 描述
* Java提供访问数据库规范称为JDBC,而生产厂商提供规范的实现类称为驱动
* JDBC是接口,驱动是接口的实现,没有驱动将无法完成数据库连接,从而不能操作数据库!
    每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生成厂商提供。

导入mysql数据库驱动程序jar包

  • A: 导入mysql数据库驱动程序jar包
* a: 步骤
    * 创建lib目录,用于存放当前项目需要的所有jar包
    * 选择jar包,右键执行build path / Add to Build Path

JDBC的开发步骤

  • A: JDBC的开发步骤
* a: 步骤介绍
    1.注册驱动
        告知JVM使用的是哪一个数据库的驱动
    2.获得连接
        使用JDBC中的类,完成对MySQL数据库的连接
    3.获得语句执行平台
        通过连接对象获取对SQL语句的执行者对象
    4.执行sql语句
        使用执行者对象,向数据库执行SQL语句
        获取到数据库的执行后的结果
    5.处理结果
    6.释放资源  一堆close()

执行insert语句获取结果集

* a: 案例代码
        public class JDBCDemo {
            public static void main(String[] args)throws ClassNotFoundException,SQLException{
                //1.注册驱动 反射技术,将驱动类加入到内容
                // 使用java.sql.DriverManager类静态方法 registerDriver(Driver driver)
                // Diver是一个接口,参数传递,MySQL驱动程序中的实现类
                //DriverManager.registerDriver(new Driver());
                //驱动类源代码,注册2次驱动程序
                Class.forName("com.mysql.jdbc.Driver");
                
                //2.获得数据库连接  DriverManager类中静态方法
                //static Connection getConnection(String url, String user, String password)  
                //返回值是Connection接口的实现类,在mysql驱动程序
                //url: 数据库地址  jdbc:mysql://连接主机IP:端口号//数据库名字
                String url = "jdbc:mysql://localhost:3306/mybase?useUnicode=true&characterEncoding=UTF-8";
                String username="root";
                String password="123";
                Connection con = DriverManager.getConnection(url, username, password);
                
                //3.获得语句执行平台, 通过数据库连接对象,获取到SQL语句的执行者对象
                // con对象调用方法   Statement createStatement() 获取Statement对象,将SQL语句发送到数据库
                // 返回值是 Statement接口的实现类对象,,在mysql驱动程序
                Statement stat = con.createStatement();
                //    4.执行sql语句
                // 通过执行者对象调用方法执行SQL语句,获取结果
                // int executeUpdate(String sql)  执行数据库中的SQL语句, insert delete update
                // 返回值int,操作成功数据表多少行
                int row = stat.executeUpdate
                        ("INSERT INTO sort(sname,sprice,sdesc) VALUES('汽车用品',50000,'疯狂涨价')");
                System.out.println(row);
                
                //6.释放资源  一堆close()
                stat.close();
                con.close();
            }
        }

执行select语句获取结果集

* a: 案例代码
        public class JDBCDemo1 {
            public static void main(String[] args) throws Exception{
                //1. 注册驱动
                Class.forName("com.mysql.jdbc.Driver");
                //2. 获取连接对象
                String url = "jdbc:mysql://localhost:3306/mybase?useUnicode=true&characterEncoding=UTF-8";
                String username="root";
                String password="123";
                Connection con = DriverManager.getConnection(url, username, password);
                //3 .获取执行SQL 语句对象
                Statement stat = con.createStatement();
                // 拼写查询的SQL
                String sql = "SELECT * FROM sort";
                //4. 调用执行者对象方法,执行SQL语句获取结果集
                // ResultSet executeQuery(String sql)  执行SQL语句中的select查询
                // 返回值ResultSet接口的实现类对象,实现类在mysql驱动中
                ResultSet rs = stat.executeQuery(sql);
                //5 .处理结果集
                // ResultSet接口方法 boolean next() 返回true,有结果集,返回false没有结果集
                while(rs.next()){
                    //获取每列数据,使用是ResultSet接口的方法 getXX方法参数中,建议写String列名
                    System.out.println(rs.getInt("sid")+"   "+rs.getString("sname")+
                            "   "+rs.getDouble("sprice")+"   "+rs.getString("sdesc"));
                }
                
                rs.close();
                stat.close();
                con.close();
            }
        }

PrepareStatement接口预编译SQL语句执行修改

* 案例代码
        /*
         *  使用PrepareStatement接口,实现数据表的更新操作
         */
        public class JDBCDemo {
            public static void main(String[] args) throws Exception{
                Class.forName("com.mysql.jdbc.Driver");
                String url = "jdbc:mysql://localhost:3296/mybase";
                String username="root";
                String password="123";
                Connection con = DriverManager.getConnection(url, username, password);    
                
                //拼写修改的SQL语句,参数采用?占位
                String sql = "UPDATE sort SET sname=?,sprice=? WHERE sid=?";
                //调用数据库连接对象con的方法prepareStatement获取SQL语句的预编译对象
                PreparedStatement pst = con.prepareStatement(sql);
                //调用pst的方法setXXX设置?占位
                pst.setObject(1, "汽车美容");
                pst.setObject(2, 49988);
                pst.setObject(3, 7);
                //调用pst方法执行SQL语句
                pst.executeUpdate();
                
                pst.close();
                con.close();
            }
        }

PrepareStatement接口预编译SQL语句执行查询

* a: 案例代码
        /*
         *  PrepareStatement接口实现数据表的查询操作
         */
        public class JDBCDemo1 {
            public static void main(String[] args) throws Exception{
                Class.forName("com.mysql.jdbc.Driver");
                String url = "jdbc:mysql://localhost:3296/mybase";
                String username="root";
                String password="123";
                Connection con = DriverManager.getConnection(url, username, password);    
                
                String sql = "SELECT * FROM sort";
                
                PreparedStatement pst = con.prepareStatement(sql);
                
                //调用pst对象的方法,执行查询语句,Select
                ResultSet rs=pst.executeQuery();
                while(rs.next()){
                    System.out.println(rs.getString("sid")+"  "+rs.getString("sname")+"  "+rs.getString("sprice")+"  "+rs.getString("sdesc"));
                }
                rs.close();
                pst.close();
                con.close();
            }
        }

JUnit:

public class TestDemo {
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    @Before
    public void init() throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mybase?useUnicode=true&characterEncoding=UTF-8","root","root");
        System.out.println("init");
    }

    @After
    public void after() throws SQLException {
        preparedStatement.close();
        connection.close();
    }

    @Test
    public void test_login() throws ClassNotFoundException, SQLException {
        // write your code here

        System.out.println(connection);
        Scanner(System.in);
        String username = "zhangsan";

        String password = "1233";

        preparedStatement
                = connection.prepareStatement("select * from users where username = ? and password = ?");
        preparedStatement.setString(1,username);
        preparedStatement.setString(2,password);


        ResultSet resultSet = preparedStatement.executeQuery();

        if(resultSet.next())
        {
            System.out.println("登录成功");
        }
        else
        {
            System.out.println("登录失败");
        }


//        6.释放资源  一堆close()
        resultSet.close();

    }

//测试用例
    @Test
    public void test_update() throws SQLException, ClassNotFoundException {
        preparedStatement
                = connection.prepareStatement("update users set username = ? where id = ?");
        preparedStatement.setString(1,"张三丰");
        preparedStatement.setInt(2,1);

        int nRows = preparedStatement.executeUpdate();
    }
}

JDBC的工具类和测试

* a: 案例代码
        //JDBCUtils工具类代码
        public class JDBCUtils {
            private JDBCUtils(){}
            private static Connection con ;
            
            static{
                try{
                    Class.forName("com.mysql.jdbc.Driver");
                    String url = "jdbc:mysql://localhost:3306/mybase";
                    String username="root";
                    String password="root";
                    con = DriverManager.getConnection(url, username, password);
                }catch(Exception ex){
                    throw new RuntimeException(ex+"数据库连接失败");
                }
            }
            
            /*
             * 定义静态方法,返回数据库的连接对象
             */
            public static Connection getConnection(){
                return con;
            }
            
            
            public static void close(Connection con,Statement stat){
                 
                 if(stat!=null){
                     try{
                         stat.close();
                     }catch(SQLException ex){}
                 }
                 
                 if(con!=null){
                     try{
                         con.close();
                     }catch(SQLException ex){}
                 }
                 
            }
            
            
            public static void close(Connection con,Statement stat , ResultSet rs){
                 if(rs!=null){
                     try{
                         rs.close();
                     }catch(SQLException ex){}
                 }
                 
                 if(stat!=null){
                     try{
                         stat.close();
                     }catch(SQLException ex){}
                 }
                 
                 if(con!=null){
                     try{
                         con.close();
                     }catch(SQLException ex){}
                 }
                 
            }
        }
    //测试JDBCUtils工具类的代码
    public class TestJDBCUtils {
        public static void main(String[] args)throws Exception {
            Connection con = JDBCUtils.getConnection();
            PreparedStatement pst = con.prepareStatement("SELECT sname FROM sort");
            ResultSet rs = pst.executeQuery();
            while(rs.next()){
                System.out.println(rs.getString("sname"));
            }
            JDBCUtils.close(con, pst, rs);
        }
    }

主方法:

Connection connection = JDBCUtils.getConnection();
JDBCUtils.close(connection,preparedStatement,resultSet);

jdbc事务处理

案例:转账操作,输入;两个用户名,然后输出一个转账金额,操作为:第一个用户给第二个用户转账指定的金额。

在金额从A用户转出完了,再转入到B账户的过程中如果系统出现故障,那么金额就不会转入到B账户了。但是A事务已经提交(只要执行了DML操作jdbc默认就是自动提交事务的)。这就造成了金额凭空丢失的问题。所以,需要让所有的操作在同一个事务中,中间任何一部出现问题就需要事务回滚,能执行到最后才能进行事务提交。

try{
//关闭自动提交
    //操作1
    //操作2
    //提交事务
}catch(){
    //回滚事务
}
这样做就能保障一组操作的完整性.
public class JDBCTrans {
    public static void main(String[] args) {
        Connection connection = null;
        try {
            Scanner scanner = new Scanner(System.in);
            System.out.println("输入转出账号:");
            String out = scanner.nextLine();
            System.out.println("输入转入账号:");
            String in = scanner.nextLine();
            System.out.println("输入转账金额");
            int account = scanner.nextInt();

            connection=DBUtil.getConnection();
            //设置事务不自动提交
            connection.setAutoCommit(false);
            //转出
            String outSql="UPDATE userinfo "
                    + "SET account=account-? "
                    + "WHERE username=?";

            PreparedStatement preparedStatement = connection.prepareStatement(outSql);

            preparedStatement.setInt(1, account);
            preparedStatement.setString(2, out);
            int m = preparedStatement.executeUpdate();
            System.out.println("---");
            if(m>0){
                System.out.println("转出成功");
            }else {
                System.out.println("转出失败");
                //不再进行转入
                return;
            }
            //转入
            String inSql="UPDATE userinfo "
                    + "SET account=account+?"
                    + "WHERE username=?";

            preparedStatement = connection.prepareStatement(inSql);
            preparedStatement.setInt(1, account);
            preparedStatement.setString(2, in);
            int n = preparedStatement.executeUpdate();
            if(n>0){
                System.out.println("转入成功");
                connection.commit();
            }else {
                System.out.println("转入失败");
                //回滚事务
                connection.rollback();
            }

        } catch (Exception e) {
            //出现异常回滚事务
            try {
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            DBUtil.closeConnection();
        }
    }
}
public class JDBCTransactionDemo {
    public static void main(String[] args) throws SQLException {
        Connection connection = JDBCUtils.getConnection();
        connection.setAutoCommit(false);

        try {
            PreparedStatement preparedStatement
                    = connection.prepareStatement("update users set money = money - 2000 where id = 3");
            preparedStatement.executeUpdate();


            preparedStatement
                    = connection.prepareStatement("update users set money = money + 2000 where id = 4");
            preparedStatement.executeUpdate();

            connection.commit();
        } catch (Exception e) {
            connection.rollback();
        }

    }
}

jdbc之批处理

批操作可以一次性向数据库端发送若干SQL语句,从而减少与数据库服务端的网络通信,提高执行效率。
当大批量执行SQL语句时,影响效率的2个因素:
1:事务,事务越多速度越慢(事务最好一次提交);
2:网络调用,网络调用越多速度越慢(这里可以使用缓存解决);
需求:向数据库中userinfo表插入10000条数据
自动提交事务,不添加缓存测试:

public class JDBCBatch {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        try {
            connection = DBUtil.getConnection();
            statement = connection.createStatement();
            long start =new Date().getTime();
            System.out.println("开始前:"+start);
            for (int i = 0; i < 10000; i++) {
                String sql="INSERT INTO userinfo "
                        + "VALUES "
                        + "(seq_userinfo_id.NEXTVAL,'test"+i+"','123456',"
                        + "5000,'test"+i+"@tedu.cn')";
                //立刻将SQL发送至数据库服务端
                statement.executeUpdate(sql);
            }

            System.out.println("结束用时:"+(new Date().getTime()-start));

        } catch (Exception e) {

        }finally {
            DBUtil.closeConnection();
        }
    }
}
输出:
开始前:1502871180710
结束用时:10757

不自动提交:

public class JDBCDemo2 {
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement pStatement;
        try {
            connection = DBUtil.getConnection();
            connection.setAutoCommit(false);
            String sql="INSERT INTO userinfo "
                    + "VALUES "
                    + "(seq_userinfo_id.NEXTVAL,?,'123456',5000"
                    + ",?)";
            pStatement = connection.prepareStatement(sql);
            long time = new Date().getTime();
            for (int i = 0; i < 10000; i++) {
                pStatement.setString(1, "aa"+i);
                pStatement.setString(2, "scu@qq.com"+i);
                pStatement.addBatch();
            }
            pStatement.executeBatch();
            System.out.println("用时:"+(new Date().getTime() - time));
            //清空本地缓存
            pStatement.clearBatch();
            connection.commit();

        } catch (Exception e) {
            try {
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            DBUtil.closeConnection();
        }
    }
}
输出:
用时:103
public class BatchInsertDemo {
    public static void main(String[] args) throws SQLException {
        Connection connection = JDBCUtils.getConnection();
        connection.setAutoCommit(false);
        PreparedStatement preparedStatement = connection.prepareStatement("insert into users(username) values(?)");

        for(int i = 0; i < 10000; i++)
        {
            preparedStatement.setString(1,"张"+i);
            preparedStatement.addBatch();
        }

        preparedStatement.executeBatch();
        connection.commit();
        System.out.println("插入完成");
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容