zoukankan      html  css  js  c++  java
  • JDBC

    JDBC

    jdbc的目标是使java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统

    Java应用程序——>JDBC API——>JDBC驱动程序——>数据库

    Java.sql.Driver接口是所有JDBC驱动程序需要实现的接口。

    》这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现

    》在程序中不需要直接访问实现了Driver接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现

    数据库厂商必须实现的接口,能从中获取数据库的连接

    /**
     * JDBC URL
     * jdbc:mysql://localhost:3306/test
     *
     * 对于oracle数据库连接:
     * jdbc:oracle:thin:@localhost:1521:sid
     *
     * 对于SQLserver数据库连接:
     * jdbc:miscrosoft:sqlserver//localhost:1433;DatabaseName=sid
     *
     * 对于MYSQL数据库连接:
     * jdbc:mysql://localhost:3306/sid
     */
    

      

    连接数据库的步骤:

    1、注册驱动(只做一次)

    2、建立连接(Connection)

    3、创建执行SQL的语句(Statment)

    4、执行语句

    5、处理执行结果(ResultSet)

    6、释放资源

     

    DriverManager 是驱动的管理类

    1)可以通过重载的getConnection()方法获取数据库连接,较为方便

    2)可以同时管理多个驱动程序:若注册多个数据库连接,则调用getConnection()方法时传入的参数不同,即返回不同的数据库连接

    		String driverClass = "oracle.jdbc.OracleDriver";
    		String url = "jdbc:oracle:thin:@localhost:1521:orcl";
    		String user = "scott";
    		String password = "123456";
    		//加载数据库驱动程序(对应的Driver实现类中有注册驱动的静态代码块)
    		//DriverManager.registerDriver((Driver) Class.forName(driverClass).newInstance());
    		Class.forName(driverClass);
    		Connection conn = DriverManager.getConnection(url, user, password);
    		System.out.println(conn);
    

     

    通过配置文件jdbc.properties获取数据库连接

    String driverClass = "oracle.jdbc.OracleDriver";
    		String url = "jdbc:oracle:thin:@localhost:1521:orcl";
    		String user = "scott";
    		String password = "123456";
    		
    		//读取配置文件信息
    		InputStream is = getClass().getClassLoader().getResourceAsStream("jdbc.properties");
    		Properties pro = new Properties();
    		
    		//将读取的配置文件信息传入pro
    		pro.load(is);
    		
    		//根据值进行查询赋值
    		driverClass = pro.getProperty("driverClass");
    		url = pro.getProperty("url");
    		user = pro.getProperty("user");
    		password = pro.getProperty("password");
    		
    		//创建一个驱动对象   Class.forName() 加载数据库驱动
    		Driver driver = (Driver) Class.forName(driverClass).newInstance();
    		Properties info = new Properties();
    		info.put("user",user);
    		info.put("password",password);
    		
    		//通过driverManager的getConnection()方法获取连接
    		Connection conn = DriverManager.getConnection(url, info);
    		
    		return conn;
    

      

     

    *增、删、改用Statement.executeUpdate来完成,返回整数(匹配的记录数),这类操作相当简单。

    *查询用Statement.executeQuery来完成,返回的是ResultSet对象,ResultSet中包含了查询的结果。

     

    创建与数据库的连接的标准方式是在

    DriverManager上调用方法getConnection().

     

    statement(语句对象)

    》executeUpdate(String sql):

    执行SQL insert,update或delete语句,返回受影响的行的数目或零;返回值为int型

    》executeQuery(String sql)

    执行返回单个ResultSet的SQL语句;返回类型ResultSet

    》execute(String sql)

    执行可以返回多个结果的SQL语句。返回类型boolean,如果返回的是更新的数目,则返回false,如果返回ResultSet,则返回true。(不常用)

    		//1.获取数据库连接
    		Connection conn = getConnection();
    		
    		//2.准备插入的sql语句
    		String sql = "insert into student values(3,'123','123')";
    
    		//3.执行插入	
    		//(1)获取操作与SQL语句的Statement对象
    		Statement state = conn.createStatement();
    		
    		//(2)调用Statement对象的executeUpdate(sql)执行SQL语句进行插入
    		int result = state.executeUpdate(sql);
    		System.out.println(result);
    		
    		//4.关闭Statement对象
    		state.close();
    		
    		//5.关闭连接
    		conn.close();
    

    PreparedStatement

    * 使用PreparedStatement
    * 1)why?
     ①使用statement需要进行拼写SQL语句。很辛苦,而且容易出错。

     ②可以有效地禁止SQL注入。

      ——SQL诸如是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入,数据中注入非法的SQL语句段

      ——对于Java而言,要规范SQL注入,只要用PreparedStatement取代Statement就可以了。

    SQL注入

    String username = "a' OR PASSWORD = ";
    String password = "OR '1' = '1";
    
    String sql = "SELECT * FROM USERS WHERE USERNAME = '" 
    			+ username + "' AND "
    			+ "PASSWORD = '" 
    			+ password
    			+ "'";
     }
    select * from users where username = 'a' or password = 'and password = ' or '1' = '1'
    

     《3》PreparedStatement能最大可能提高性能


    * 2)PreparedStatement:是Statement的子接口,可以传入带占位符的SQL语句,而且
    * 提供了补充占位符变量的方法。
    *
    * 使用PreparedStatement
    * ①创建PreparedStatement:
    * String sql = "INSERT INTO STUDENT VALUES(?,?,?,?,?)"
    * PreparedStatement ps = conn.prepareStatement(sql);
    *
    * ②调用PreparedStatement的setXxx(int index,Object val)设置占位符的值。
    * index值从1开始
    *
    * 3执行SQL语句:executeQuery()或executeUpdate().注意:执行时不再需要传入SQL语句

    	@Test
    	public void test2(){
    		Connection conn = null;
    		PreparedStatement preparedStatement = null;
    		
    		try {
    			conn = getConnection();
    			String sql = "insert into examstudent values(?,?,?,?,?,?,?)";
    			
    			preparedStatement =  conn.prepareStatement(sql);
    			
    			preparedStatement.setInt(1,11);
    			preparedStatement.setInt(2, 2);
    			preparedStatement.setString(3, "43121223113");
    			preparedStatement.setString(4,"1245523");
    			preparedStatement.setString(5,"yhs");
    			preparedStatement.setString(6,"dwd");
    			preparedStatement.setInt(7,3);
    			
    			int re = preparedStatement.executeUpdate();
    			if(re ==1){
    				System.out.println("插入成功!!!");
    			}
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}finally{
    			release(preparedStatement, conn, null);
    		}
    	}
    

      

    ResultSet

    结果集读取数据的方法主要是getXXX(),他的参数可以使整数表示第几列(从1开始的),还可以是列名。

    返回的是对应的XXX类型的值。如果对应那列时空值,XXX是对象的话返回XXX型的空值,如果XXX是数字类型,如Float等返回0,boolean返回false

    结果集,封装了使用JDBC进行查询的结果

    1.调用Statement对象的executeQuery(sql)可以得到结果集

    2.ResultSet返回的实际上就是一张数据表,有一个指针指向数据表的第一行的前面

    可以使用next()方法检测下一行是否有效,若有效该方式返回true,且指针下移。

    相当于Iterator对象的hasNext()和next()方法的结合体

    3.当指针对位到一行时,可以通过getXxx(index)或getXxx(columnName)

    获取每一列的值,例如:getInt(1),getString("name")

    4.ResultSet:当然也需要进行关闭

    单条数据查询:

    		Connection conn = getConnection();
    		Statement state = conn.createStatement();
    		
    		String sql = "select * from student where id=1";
    		ResultSet rs = state.executeQuery(sql);
    		if(rs.next()){
    			int id = rs.getInt(1);
    			String name = rs.getString("name");
    			String password = rs.getString("password");
    			
    			System.out.println(id);
    			System.out.println(name);
    			System.out.println(password);
    		}
    		
    		conn.close();
    		state.close();
    		rs.close();
    

     

    多条数据查询:

    		Connection conn = getConnection();
    		Statement state = conn.createStatement();
    		
    		String sql = "select * from student";
    		ResultSet rs = state.executeQuery(sql);
    		while(rs.next()){
    			int id = rs.getInt(1);
    			String name = rs.getString("name");
    			String password = rs.getString("password");
    			
    			System.out.print(id + "  ");
    			System.out.print(name + "  ");
    			System.out.println(password);
    		}
    		
    		conn.close();
    		state.close();
    		rs.close();
    

      

    封装查询多个对象的方法:

    ResultSetMetaData:(解决红色部分)接口

    1)what:是描述ResultSet的元数据对象,即从中可以获取到结果集有多少列,列名是什么....

    2) how:

    <1>得到ResultSetMetaData  对象:调用ResultSet的getMetaData()方法

    <2>ResultSetMetaData有哪些好用的方法

      >int getColumnCount(): SQL语句包含哪些列

      >String getColumnLabel(int column):获取指定的列的别名,其中索引从1开始。

    获取结果集每一列的别名

    for(int i=0;i<rsmd.getColumnCount();i++){

      String columnLabel = rsmd.getColumnLabel(i+1);

    }

     

    public <T> T testResultSetMetaData(Class<T> clazz,String sql,Object...args){
    		Connection conn = null;
    		PreparedStatement preparedstatement = null;
    		ResultSet resultset = null;
    		T entity = null;
    		
    		try {
    			conn = getConnection();
    			preparedstatement = conn.prepareStatement(sql);
    			//对sql占位符进行赋值
    			for(int i=0;i<args.length;i++){
    				preparedstatement.setObject(i+1,args[i]);
    			}
    			resultset = preparedstatement.executeQuery();
    			
    			ResultSetMetaData metaData = resultset.getMetaData();
    				
    			Map<String,Object> map = new HashMap<String,Object>();
    			while(resultset.next()){
    				for(int i=0;i<metaData.getColumnCount();i++){
    					String columnLabel = metaData.getColumnLabel(i+1);
    					Object obj = resultset.getObject(i+1);
    					map.put(columnLabel, obj);
    					System.out.println(columnLabel + " " +obj);
    				}
    			}
    			if(map.size()>0){
    				entity = clazz.newInstance();
    				
    				//遍历Map对象,利用反射为Class对象对应的属性赋值
    				for(Map.Entry<String, Object> entry : map.entrySet()){
    					String fieldName = entry.getKey();
    					Object value = entry.getValue();
    					BeanUtil
    				}
    			}
    			
    		} catch (Exception e) {
    			// TODO: handle exception
    		}finally{
    			release(preparedstatement, conn, resultset);
    		}
    		return null;
    	}
    	
    

      

  • 相关阅读:
    文本比较算法Ⅳ——Nakatsu算法
    网游中,“时间停止的实现”的设想
    GDI+绘制自定义行距的文本(续)
    GDI+绘制自定义行距的文本的三种方法。
    文本比较算法Ⅱ——Needleman/Wunsch算法
    文本比较算法Ⅲ——计算文本的相似度
    javascript笔记:深入分析javascript里对象的创建(上)续篇
    java笔记:自己动手写javaEE框架(五)Spring事务管理学习
    java笔记:自己动手写javaEE框架(三)引入SQL监控技术P6spy
    java笔记:自己动手写javaEE框架(一)数据访问层DAO以及DAO的单元测试
  • 原文地址:https://www.cnblogs.com/yangHS/p/10740224.html
Copyright © 2011-2022 走看看