JDBC

JDBC

jdbc: java连接数据库的一套规范
    各个数据库实现这一套规范,就是该数据库的驱动jar包(驱动jar包的版本号与数据库的版本号不是一一对应,可以互相兼容的)
    jdbc与数据库驱动的关系就是接口与实现的关系
    
    
类加载器加载类里面的文件?
    inputStream = MyConnection.class.getClassLoader().getResourceAsStream("jdbc.properties");
        Properties properties = new Properties();
        properties.load(inputStream);


所以java连接数据库:
第一步,导入要连接的数据库的驱动jar包,
第二步,代码加载驱动jar包
   使用反射加载, Class.forName("com.mysql.jdbc.Driver") ,耦合度低,只加载一次
         基本不这样写:1) DriverManager.registerDiver(new Driver());     因为在mysql实现的驱动Driver里的静态块已经注册了驱动,new的时候静态块加载一次,
                                                                       registerDiver又加载一次,导致mysql底层会注册两次
                       2) new Driver()       -----》   可以省略DriverManager.registerDiver,但是当前程序就跟Mysql驱动绑定,以后不能没有扩展性,耦合度比较高


核心对象:
DriverManager 用于注册驱动 静态工具类
Connection 表示与数据库创建的连接 DriverManager.getConnection
Statement 操作数据库sql语句的对象 connection.createStatement();    ---  使用PreparedStatement替代它
ResultSet 结果集或一张虚拟表 statement.getResultSet()
           除了next,不要使用ResultSet的方法遍历,
           可以转化为list,map再遍历
           更好的是使用jdk8的stream流式编程(jdk8,lambda表达式、stream流式编程)
           
             resultSET,没有查询到结果,返回值有的,不是null
           ---ResultSet 对象没有下一行时返回 false

由于Statement的执行效率低,并且sql拼接会出现sql的注入,所以引出了:
PreparedStatement,预编译的Statement,性能比较高,可以缓存经常执行的sql语句
                   用占位符的方式去传值,不用拼接字符串,避免了sql注入!
                   
Connection可以多个方法共享,statement不能被多个方法共享
                   
                   
常用的实现框架:
MyBatis: 国内最流行的jdbc封装框架,sql语句写在xml里,返回值转化为bean,不用我们再封装成对象(亲力亲为,但是可以很好的优化)
Hibernate:冬眠的意思,让sql冬眠,面向对象的数据库编程,现在国外比较流行的持久化框架,国内低调
            底层封装复杂的sql,难优化,适用于中小型项目
JPA: sun提出面向对象编程的规范(从hibernate学习的规范)    ----》 JPA是一个规范,不是框架
      有hibernate实现,spring实现(基本spring一统天下)
      对jdbc的改进优化有什么想法,提JPA
      

一般对数据库表数据的查询删除等,都是通过主键id来查询判断的,不要使用name其它字段,除非是业务需求


-----

操作数据库:


idea中,jdbc中executeUpdate( "update cat set age=age+100" );点开document窗口,里面会显示表的数据结构!!!,当然,前提是已经连接了数据库
把sql抽取出来写: String sql = "update cat set age=age+100" ,document窗口,不会会显示表的数据结构,但是数据库可以校验写的表,,,
     
代码的重构: 把相似的代码提取出来,重复调用
利用继承关系,面向接口编程,即模板模式编程:  子类实现业务代码,父类实现重复的代码!

单元测试: beforeclass,afterclass,before,after的使用

executeUpdate: 用来执行(insert ,update,delete),没有结果集的返回值,只有影响行数的返回值
               public class ConnectionTest {
                    static Connection connection = null;
                    //如果每个单元测试方法都要使用statement,放到@Before修饰的方法里面,保证每次执行单元测试时候都会初始化这个对象
                    Statement statement=null;

                    @BeforeClass
                    //用来设定每次进行单元测试之前都初始化一次的函数
                    public static void beforeClass() throws Exception {
                        Class.forName( "com.mysql.jdbc.Driver" );

                        //定义连接数据库的url ,用来指定怎么样找到哪个数据库
                        //格式如下: 协议 子协议  IP :端口号 数据库
                        String url = "jdbc:mysql://localhost:3306/bg_1904?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";
                        String user = "root";
                        String password = "";

                        //2.JDBC第二步  通过注册管理器得到数据库的连接Connection
                        connection = DriverManager.getConnection( url, user, password );
                    }

                    @Before
                    public void before() throws SQLException {
                         statement = connection.createStatement();
                    }


                    @Test
                    public void testExecuteUpdate() throws SQLException {
                        //executeUpdate用来执行(insert ,update,delete),没有结果集的返回值,只有影响行数的返回值
                        int i = statement.executeUpdate( "update cat set age=age+100" );
                        int j = statement.executeUpdate( "insert into cat values ('jerry',50)" );
                        statement.executeUpdate( "delete from cat where name='jerry'" );
                    }

                    @After
                    public void after() {
                        if (statement!=null) {
                            try {
                                statement.close();
                            } catch (SQLException e) {
                            }
                        }
                    }


                    @AfterClass
                    public static void afterClass() {
                        if (connection != null) {
                            try {
                                connection.close();
                            } catch (SQLException e) {
                            }
                        }

                    }
                }


---------

executeQuery : 用来执行select语句,返回值是一个结果集ResultSet;  
               默认提供一个游标,指向第一行的之前,如果判断当前数据库有没有记录,就要判断next()后有没有数据
               
            ResultSet resultSet = statement.executeQuery( "select name as catName,age as catAge from cat" );
            //获取数据的第一种方式:
            if (resultSet.next()) {

                //getObject严格的说,是根据列的别名来获取值,如果没有别名那就写列名
                Object name = resultSet.getObject( "catName" );        
                System.out.println( "name = " + name );
              
            }

            //获取数据的第二种方式:通过在getObject传入列的序号(注意:从1开始)
            if (resultSet.next()) {
                Object name = resultSet.getObject( 1 );
                Object age = resultSet.getObject( 2 );

                System.out.println( "ResultSetTest.testResultSet   " +name);         
            }
            
            //关闭结果集
            if (resultSet != null) {
                resultSet.close();
            }
        
------------

execute:
        /**
         * execute方法用来执行sql,查询类型select和修改类型update delete insert都可以执行
         *  返回类型:
         *     1>true: 表示当前执行的是select方法,在statement里面包含里结果集getResultSet
         *     2>false 表示当前执行的是update,insert ,delete其中之一的方法,通过getUpdateCount得到影响的结果整型数值
         *
         */
        boolean execute = statement.execute( "delete  from cat where name='jerry'" );
        if (execute) {
            ResultSet resultSet = statement.getResultSet();
            while (resultSet.next()) {
                System.out.println( "resultSet.getObject(1) = " + resultSet.getObject( 1 ) );
                System.out.println( "resultSet.getObject(2) = " + resultSet.getObject( 2 ) );
            }
        } else {
            //表示执行的是update insert delete更新语句
            int updateCount = statement.getUpdateCount();
            System.out.println("执行的是更新语句,影响的行数为:"+updateCount);
        }

        

--------------------
PreparedStatement:预编译的Statement,性能比较高,可以缓存经常执行的sql语句
                   用占位符的方式去传值,不用拼接字符串,避免了sql注入!

       PreparedStatement preparedStatement = connection.prepareStatement( sql );

        int index=1;

        //给preparedStatement对象传参,从1开始传参,
        //小技巧,如果有多个参数传入,并且以后还会添加参数,那么传参的索引一般用index++代替扩展性比较强
        preparedStatement.setObject( index++, userName );
        preparedStatement.setObject( index++, password );

        ResultSet resultSet = preparedStatement.executeQuery();    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值