JDBC的基本用法

    JDBC(Java Database Connection)是Java提供的数据库连接标准,具体的标准实现由各个数据库厂商提供。

    下面以MySQL为例来简单演示JDBC接口的基本用法。

     JDBC连接数据库的基本步骤如下:

     1.加载要连接的数据库驱动,运用了反射机制。

        加载MySQL驱动的代码为:Class.forName("com.mysql.jdbc.Driver");

     2.通过DriverManager来获取与要连接的数据库的一个连接。

        代码格式为:DriverManager.getConnection(c, "root", "1234");

        其中字符串c为"jdbc:mysql://localhost:3306/databaseName?useUnicode=true&characterEncoding=utf8";

        后面的字符串指定有可能对解决中文乱码问题有帮助,如果数据库默认编码支持中文也可以不设置。

     以上两个步骤完成后就完成了数据库的连接,如果想要进一步对数据库操作,要根据不同的应用情景来实现。

     1)通过Statement来获取并执行SQL语句。

          缺点:容易造成SQL注入,对数据库造成安全隐患。但是在执行SQL批处理时可以很方便的使用。

          下面代码可以体现其用法。

     

package com.wxisme.jdbc01;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
 * 连接MySQL基本流程
 * @author wxisme
 *
 */
public class Demo02 {

	public static void main(String[] args) {
		Connection con = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			//先加载数据库驱动
			Class.forName("com.mysql.jdbc.Driver");
			//通过驱动管理来建立连接
			String c = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8";
			con = DriverManager.getConnection(c, "root", "1234");
			//创建statement  
			String sql = "select * from student where b='张三'";
			stmt = con.createStatement();
			//创建结果集  不能预编译SQL  只能在执行时传入SQL
			rs = stmt.executeQuery(sql);
			//next()指针指向下一条记录,如果有返回true,否则返回false
			while(rs.next()) {
				for(int i=1; i<10; i++) {
					//getString()可以传入字段名,也可以传入字段的Index
					System.out.print(rs.getString(i)+"    ");
				}
				System.out.println();
			}
			
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}finally {
			
			try {
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
				
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
            try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
	}

}

     2)通过prepareStatement预编译SQL,防止SQL注入。

          优点:可以防止SQL注入并预编译SQL可以提高效率,可以使用?占位符,写SQL语句时不用拼字符串,不容易出错。但是在批量处理时不方便使用。

         

public class Demo01 {

	public static void main(String[] args) {
		Connection con = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			//先加载数据库驱动
			Class.forName("com.mysql.jdbc.Driver");
			//通过驱动管理来建立连接
			String c = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8";
			con = DriverManager.getConnection(c, "root", "1234");
			//创建statement  
			String sql = "select * from student where b=?";
			stmt = con.prepareStatement(sql);
			
			stmt.setString(1, "张三");
			
			//创建结果集
			rs = stmt.executeQuery();
			
			while(rs.next()) {
				for(int i=1; i<10; i++) {
					System.out.print(rs.getString(i)+"    ");
				}
				System.out.println();
			}
			
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}finally {
			
			try {
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
				
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
            try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
	}

}

     3)使用批处理一次提交执行批量SQL语句。

      

public class Demo03 {

	public static void main(String[] args) {
		Connection con = null;
		Statement stmt = null;
		try {
			//先加载数据库驱动
			Class.forName("com.mysql.jdbc.Driver");
			//通过驱动管理来建立连接
			String c = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8";
			con = DriverManager.getConnection(c, "root", "1234");
			con.setAutoCommit(false);//将连接的事务设为手动提交
			//创建statement  
			stmt = con.createStatement();
			for(int i=0; i<900000; i++) {
				String sql = "insert into student (a,b,c) values('中文','刘琦','2013010')";
				stmt.addBatch(sql);
			}
			stmt.executeBatch();
			con.commit();//提交事务
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}finally {
			
			try {
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
				
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
	}

}

    4)数据库事务的提交和回滚,在默认情况下,数据库事务是自动提交的,但是如果手动提交,在最后调用数据库连接的回滚方法,在一个SQL语句有了错误抛出异常后,其他的SQL语句都不再执行,已经执行的SQL语句回滚到以前的状态,就是如果有异常抛出则数据库中的数据不会发生变化。

       

package com.wxisme.jdbc01;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
/**
 * 事务的手动提交和回滚
 * @author wxisme
 *
 */
public class Demo04 {

	public static void main(String[] args) {
		Connection con = null;
		PreparedStatement stmt = null;
		
		try {
			//先加载数据库驱动
			Class.forName("com.mysql.jdbc.Driver");
			//通过驱动管理来建立连接
			String c = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8";
			con = DriverManager.getConnection(c, "root", "1234");
			//创建statement  
			con.setAutoCommit(false);//设置为手动提交事务
			String sql = "insert into student (?) values(?)";
			stmt = con.prepareStatement(sql);
			
			stmt.setString(1, "a");
			stmt.setString(2, "刘琦");
			con.commit();//手动提交事务
			
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
			try {
				con.rollback();//如果出现异常则回滚事务
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}finally {
			
			try {
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
				
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
           
		}
		
	}

}

     5)对日期的支持,在java.sql包中有Date,Time,Timestamp类来支持时间和日期的处理。

        

package com.wxisme.jdbc01;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Random;


/**
 * 时间处理java.sql.Date,Time,Timestamp
 * 插入带有日期和时间戳类型字段的记录
 * @author wxisme
 *
 */
public class Demo05 {
	public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			//加载驱动类
			Class.forName("com.mysql.jdbc.Driver");
			String c = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8";
			conn = DriverManager.getConnection(c, "root", "1234");
			
			for(int i=0;i<1000;i++){
				
				ps = conn.prepareStatement("insert into student (name,pswd,time,stime) values (?,?,?,?)");
				ps.setObject(1, "流苏款"+i);
				ps.setObject(2, "123456");

				int rand =  100000000+new Random().nextInt(1000000000);
				
				java.sql.Date date = new java.sql.Date(System.currentTimeMillis()-rand);
				Timestamp stamp = new Timestamp(System.currentTimeMillis()-rand);  //如果需要插入指定日期,可以使用Calendar、DateFormat
				
				ps.setDate(3, date);
				ps.setTimestamp(4, stamp);
				ps.execute();
				
			}
			
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			try {
				if(ps!=null){
					ps.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				if(conn!=null){
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}
package com.wxisme.jdbc01;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;


/**
 * 时间处理java.sql.Date,Time,Timestamp
 * 查找某个时间段的记录
 * @author wxisme
 *
 */

public class Demo06 {
	
	/**
	 * 将字符串代表的日期转为long数字(格式:yyyy-MM-dd hh:mm:ss)
	 * @param dateStr
	 * @return
	 */
	public static long str2Date(String date) {
		DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		try {
			return format.parse(date).getTime();
		} catch (ParseException e) {
			e.printStackTrace();
			return 0;
		}
	}
	
	
	public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			//加载驱动类
			Class.forName("com.mysql.jdbc.Driver");
			String c = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8";
			conn = DriverManager.getConnection(c, "root", "1234");
			
			ps = conn.prepareStatement("select * from student where stime>? and stime<?  order by stime ");
			Timestamp start = new Timestamp(str2Date("2015-5-1 8:10:20"));
			Timestamp end = new Timestamp(str2Date("2015-5-1  9:9:10"));
			ps.setObject(1, start);
			ps.setObject(2, end);
			rs = ps.executeQuery();
			while(rs.next()){
				System.out.println(rs.getString("name")+"--"+rs.getTime("time")+"--"+rs.getTimestamp("stime"));
			}
			
			
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			try {
				if(ps!=null){
					ps.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				if(conn!=null){
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

 总结:JDBC把数据库连接封装的很好,总的步骤是固定的,写几个Demo之后就熟悉了,但是在数据库连接时要注意很多细节问题,代码写的严谨才不会出BUG。

原文地址:https://www.cnblogs.com/wxisme/p/4502210.html