Java JDBC详解

一、详细步骤

1、加载数据库驱动

Class.forName("com.mysql.jdbc.Driver");

注意:如果连接的是SQLServer

Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");

2、建立连接

String url = "jdbc:mysql://localhost:3306/javastudy";
String username = "root";
String password = "521216";
Connection connection = null;
			
//2.获取与数据库的链接
connection = DriverManager.getConnection(url, username, password);

1、数据库URL

URL用于标识数据库的位置,程序员通过URL地址告诉JDBC程序连接哪个数据库。

常用数据库URL地址的写法:

  • Oracle:jdbc:oracle:thin:@localhost:1521:javastudy

  • SqlServer:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=javastudy

  • MySql:jdbc:mysql://localhost:3306/javastudy

2、Connection

Jdbc程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,创建方法为:

Connection connection = DriverManager.getConnection(url, user, pass); 

这个对象的常用方法:

方法描述
createStatement()创建向数据库发送sql的statement对象。
prepareStatement(sql)创建向数据库发送预编译sql的PrepareSatement对象。
prepareCall(sql)创建执行存储过程的callableStatement对象。
setAutoCommit(boolean autoCommit)设置事务是否自动提交。
commit()在链接上提交事务。
rollback()在此链接上回滚事务。

3、执行SQL语句

### 1、Statement

Jdbc程序中的Statement对象用于向数据库发送SQL语句,创建方法为:

Statement statement = connection.createStatement();

Statement对象常用方法:

方法含义
executeQuery(String sql)用于向数据发送查询语句。
executeUpdate(String sql)用于向数据库发送insert、update或delete语句
execute(String sql)用于向数据库发送任意sql语句
addBatch(String sql)把多条sql语句放到一个批处理中。
executeBatch()向数据库发送一批sql语句执行。
//3.获取用于向数据库发送sql语句的statement
Statement statement = connection.createStatement();
//4.向数据库发sql
String sql = "select id,name,password,email,birthday from users";
st.executeQuery(sql);

2、PreparedStatement

PreparedStatement接口继承Statement,它的实例对象可以通过调用:

 PreperedStatement st =  connection.preparedStatement();
PreperedStatement st = null;
String sql = "select * from users where name=? and password=?";

//3.获取用于向数据库发送sql语句的Preperedstatement
st = conn.preparedStatement(sql);//在此次传入,进行预编译
st.setString(1, username);
st.setString(2, password);
//4.向数据库发sql
st.executeQuery();//在这里不需要传入sql

3、PreparedStatement较Statement的优势:

  • 代码的可读性和可维护性,PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。

  • Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。

    SQL语句在被DB的编译器编译后,执行代码会被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)就会得到执行。

    当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果,以保存有更多的空间存储新的预编译语句。

  • 极大地提高了安全性,避免SQL注入的问题

4、获取结果(行列都是从1开始)

Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式,ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。

ResultSet rs = null;
//4.向数据库发sql,并获取代表结果集的resultset
String sql = "select id,name,password,email,birthday from users";
rs = st.executeQuery(sql);
//循环取出(id)
while(rs.next()){
    String id = rs.getString(1);//1代表数据库中表的列数,id在第一列也可以("id")!!!
	System.out.println("id:" + id);
}

1、获取行

ResultSet提供了对结果集进行滚动的方法:

方法含义
next()移动到下一行
previous()移动到前一行
absolute(int row)移动到指定行
beforeFirst()移动resultSet的最前面
afterLast()移动到resultSet的最后面

2、获取值

ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法:

方法含义
getObject(int index)根据列的下标返回任意类型的数据
getObject(string columnName)根据列名返回任意类型的数据
getString(int index)根据列的下标返回指定类型的数据
getString(String columnName)根据列名返回指定类型的数据

附加:

常用数据类型转换:

SQL类型JDBC对应的方法返回类型
bit(1),bit(n)getBoolean,getBytes()Boolean,byte[]
tinyintgetByte()Byte
smallintgetShort()Short
intgetIntInt
bigintgetLong()Long
char,varchar,longvarchargetStringString
text(clob),blobgetClob(),getblob()Clob,blob
dategetDate()java.sql.Date
timegetTime()java.sql.Time
timestampgetTimestampjava.sql.Timestamp

5、释放资源

Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。

注意:为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。

//6.关闭链接,释放资源
	if(rs!=null){
		try{
			rs.close();
		}catch (Exception e) {
			e.printStackTrace();
		}
		rs = null;
	
	}
	if(st!=null){
		try{
			st.close();
		}catch (Exception e) {
			e.printStackTrace();
		}
				
	}	
	if(conn!=null){
		try{
			conn.close();
		}catch (Exception e) {
			e.printStackTrace();
		}
    }

二、完整操作

数据库工具类:

public class JdbcUtils {
 
	private static String driver = null;
	private static String url = null;
	private static String username = null;
	private static String password = null;
	
    //静态代码块,随着类的加载而执行,而且只执行一次
    //父类静态代码块->子类静态代码块->子类main方法->父类非静态代码块->子类静态代码块->父类构造函数->子类构造函数
	static{
		try{
            //加载db.properties文件
			InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
			Properties prop = new Properties();
			prop.load(in);
			
            //从资源文件中取出字段值
			driver = prop.getProperty("driver");
			url = prop.getProperty("url");
			username = prop.getProperty("username");
			password = prop.getProperty("password");
			
            //加载数据库驱动
			Class.forName(driver);
			
		}catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
	}
	
    
	//获取数据库连接对象Connection
	public static Connection getConnection() throws SQLException{
        //建立连接
		return DriverManager.getConnection(url, username, password);
	}
	
    
    //释放资源(因为PreparedStatement是Statement的子类,所以定义Statement可以释放两种方式)
	public static void release(Connection conn,Statement st,ResultSet rs){
		if(rs!=null){
			try{
				rs.close();
			}catch (Exception e) {
				e.printStackTrace();
			}
			rs = null;
		}
        
		if(st!=null){
			try{
				st.close();
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		if(conn!=null){
			try{
				conn.close();
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
    
}

资源文件:db.properties:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/javastudy
username=root
password=521216

功能实现:

//使用jdbc对数据库增删改查
public class Demo {
 
	@Test
	public void insert(){
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		try{
			conn = JdbcUtils.getConnection();
            String sql = "insert into users(id,name,password,email,birthday) values(?, ?, ?, ?, ?)";
			st = conn.preparedStatement(sql);
            st.setInt(1, 4);
            st.setString(2, "xxx");
            st.setString(3, "123");
            st.setString(4, "156@qq.com");
            st.setDate(5, new Date().getTime);
            
			int num = st.executeUpdate();  //update
			if(num>0){
				System.out.println("插入成功!!");
			}
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
	}
	
	@Test
	public void delete(){
		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		try{
			conn = JdbcUtils.getConnection();
			String sql = "delete from users where id=?";
			st = conn.preparedStatement(sql);
            st.setInt(1, 4);
            
			int num = st.executeUpdate();
			if(num>0){
				System.out.println("删除成功!!");
			}
		}catch (Exception e) {
			
			
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
	}
	
	@Test
	public void update(){
		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		try{
			conn = JdbcUtils.getConnection();
			String sql = "update users set name='wuwang',email='wuwang@sina.com' where id=3";
			st = conn.createStatement();
			int num = st.executeUpdate(sql);
			if(num>0){
				System.out.println("更新成功!!");
			}
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
	}
	
	@Test
	public void find(){
		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		try{
			conn = JdbcUtils.getConnection();
			String sql = "select * from users where id=?";
			st = conn.preparedStatement(sql);
            st.setInt(1, 1);
            
			rs = st.executeQuery(sql);
			if(rs.next()){
				System.out.println(rs.getString("name"));
			}
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
	}
	
}

三、常见操作

1、处理大数据

1.存取文本文件(.txt文件)

clob用于存储大文本(mysql中无clob,存储大文本采用的是text

注意:

​ mysql:tinytext<256b text<64k mediumtext<16m longtext<4g

数据库:

	create table testclob
	(
		id int primary key auto_increment,
        resume text
	);

Java代码:

public class Demo {
	@Test
	public void add() {
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		
		try{
			conn = JdbcUtils.getConnection();
			String sql = "insert into testclob(resume) values(?)";
			st = conn.prepareStatement(sql);
			
			//Reader reader = new InputStreamReader(Demo.class.getClassLoader().getResourceAsStream("1.txt"));
			String path  = Demo.class.getClassLoader().getResource("1.txt").getPath();//1.txt文件在src下
			File file = new File(path);
			st.setCharacterStream(1, new FileReader(file), (int) file.length());//将该文件添加
            
			int num = st.executeUpdate();
			if(num>0){
				System.out.println("插入成功!!");
			}
            
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
	}
	
	@Test
	public void read(){
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		
		try{
			conn = JdbcUtils.getConnection();
			String sql = "select resume from testclob where id=1";
			st = conn.prepareStatement(sql);
            
			rs = st.executeQuery();
			if(rs.next()){
				System.out.println("haha");
				Reader reader = rs.getCharacterStream("resume");
				char[] buffer = new char[1024];
				int len = 0;
				FileWriter out = new FileWriter("d:\\1.txt");
				while((len = reader.read(buffer)) > 0){
					out.write(buffer, 0, len);
				}
				out.close();
				reader.close();
			}
			
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
	}
    
}

2、存取二进制文件(图片,视频)

注意:

​ mysql:tinyblob<256b blob<64k mediumblob<16m longblob<4g

数据库:

	create table testblob
	(
		id int primary key auto_increment,
		image longblob
	);

Java代码:

public class Demo {
	@Test
	public void add(){
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		
		try{
			conn = JdbcUtils.getConnection();
			String sql = "insert into testblob(image) values(?)";
			st = conn.prepareStatement(sql);
            
			String path = Demo2.class.getClassLoader().getResource("01.jpg").getPath();
			st.setBinaryStream(1, new FileInputStream(path), (int) new File(path).length());
            
			int num = st.executeUpdate();
			if(num>0){
				System.out.println("插入成功!!");
			}
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
	}
	
	@Test
	public void read(){
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		
		try{
			conn = JdbcUtils.getConnection();
			String sql = "select image from testblob where id=?";
			st = conn.prepareStatement(sql);  
			st.setInt(1, 1);
            
			rs = st.executeQuery();
			if(rs.next()){
				InputStream in = rs.getBinaryStream("image");
				int len = 0;
				byte buffer[] = new byte[1024];
				
				FileOutputStream out = new FileOutputStream("d:\\1.jpg");
				while((len = in.read(buffer)) > 0){
					out.write(buffer,0, len);
				}
				in.close();
				out.close();
			}
            
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
	}
}

2、批量处理SQL

数据库:

	create table testbatch
	(
		id int primary key,
		name varchar(20)
	);

1、通过Statement

	@Test
	public void testbatch(){
		
		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		
		try{
			conn = JdbcUtils.getConnection();
			String sql1 = "insert into testbatch(id,name) values(1,'aaa')";
			String sql2 = "insert into testbatch(id,name) values(2,'bbb')";
			String sql3 = "delete from testbatch where id=1";
			
			st = conn.createStatement();
			st.addBatch(sql1);
			st.addBatch(sql2);
			st.addBatch(sql3);
			
			st.executeBatch(); 
			st.clearBatch();
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
	}

2、通过preparedstatement

	@Test
	public void testbatch(){
		
		long starttime = System.currentTimeMillis();
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		
		try{
			conn = JdbcUtils.getConnection();
			String sql = "insert into testbatch(id,name) values(?,?)";
			st = conn.prepareStatement(sql);
			
			for(int i=1;i<10000008;i++){  //i=1000  2000
				st.setInt(1, i);
				st.setString(2, "aa" + i);
				st.addBatch();
				
				if(i%1000==0){
					st.executeBatch();//只有1000条数据
					st.clearBatch();
				}
			}
			st.executeBatch();//没用了
			
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
		
		long endtime = System.currentTimeMillis();
		
		System.out.println("程序花费时间:" + (endtime-starttime)/1000 + "秒!!");
	}

3、获取自动生成的主键

数据库:

	create table test1
	(
		id int primary key auto_increment,//id自动生成
		name varchar(20)
	);

Java代码:

public class Demo {
 
	/**
	 * 获取自动生成的主键
	 */
	public static void main(String[] args) {
		
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		
		try{
			conn = JdbcUtils.getConnection();
			String sql = "insert into test1(name) values(?)";
			st = conn.prepareStatement(sql);
			st.setString(1, "aaa");//在插入name时数据库会自动生成id
			st.executeUpdate();
			
			rs = st.getGeneratedKeys();//获取生成的主键
			if(rs.next()){
				System.out.println(rs.getInt(1));
			}
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
	}
    
}

4、调用存储过程

public class Demo {
	/*
	* jdbc调用存储过程:
		create procedure p_course_insert
		@c_no nvarchar(50),
		@c_name nvarchar(50),
		@t_name nvarchar(50)
		as
		insert into t_course(c_no,c_name,t_name)
		values(@c_no,@c_name,@t_name)
	*/
	public static void main(String[] args) {
		Connection conn = null;
		CallableStatement cs = null;
		ResultSet rs = null;
		
		try{
			conn = JdbcUtils.getConnection();
			cs = conn.prepareCall("{call p_course_inser(?,?,?)}");
			cs.setString(1, "xxxxx");
			cs.registerOutParameter(2, Types.VARCHAR);
			
			cs.execute();
			String result = cs.getString(2);
			System.out.println(result);
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.release(conn, cs, rs);
		}
	}
 
}

5、使用事务

1、普通事务的操作

	/**
	* 模似转帐
		create table account(
			id int primary key auto_increment,
			name varchar(40),
			money float
		)character set utf8 collate utf8_general_ci;
		
		insert into account(name,money) values('aaa',1000);
		insert into account(name,money) values('bbb',1000);
		insert into account(name,money) values('ccc',1000);
	*/
	public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		
		try{
			conn = JdbcUtils.getConnection();
			conn.setAutoCommit(false);   //start transaction,开启事务
			
			String sql1 = "update account set money=money-100 where name='aaa'";
			st = conn.prepareStatement(sql1);
			st.executeUpdate();
			
			
			String sql2 = "update account set money=money+100 where name='bbb'";
			st = conn.prepareStatement(sql2);
			st.executeUpdate();
			
			
			conn.commit();//提交
			
			System.out.println("成功!!!");  //log4j
			
		}catch (Exception e) {
			e.printStackTrace();//如果程序出错手动回滚
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
		
	}

2、设置事务回滚点

	public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		Savepoint sp = null;
		
		try{
			conn = JdbcUtils.getConnection();
			conn.setAutoCommit(false);   //start transaction
			
			String sql1 = "update account set money=money-100 where name='aaa'";
			st = conn.prepareStatement(sql1);
			st.executeUpdate();
			
			sp = conn.setSavepoint();//在这里设置事务回滚点
			
			String sql2 = "update account set money=money+100 where name='bbb'";
			st = conn.prepareStatement(sql2);
			st.executeUpdate();
			
			int x = 1/0;
			
			String sql3 = "update account set money=money+100 where name='ccc'"; 
			st = conn.prepareStatement(sql3);
			st.executeUpdate();
			
			conn.commit();
			
		}catch (Exception e) {
			try {
				conn.rollback(sp);//回滚到该事务点,即该点之前的会正常执行(sql1)
				conn.commit();  //回滚了要记得提交,如果没有提交sql1将会自动回滚
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally{
			JdbcUtils.release(conn, st, rs);
		}
		
	}

3、设置事务隔离级别

conn = JdbcUtils.getConnection();
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);//避免脏读
conn.setAutoCommit(false);
/*
Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)
Repeatable read:可避免脏读、不可重复读情况的发生。(可重复读)
Read committed:可避免脏读情况发生(读已提交)。
Read uncommitted:最低级别,以上情况均无法保证。(读未提交)
*/
隔离级别脏读可能性不可重复读可能性幻读可能性加锁读
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZALBLE

​ 注意:不是事务隔离级别设置得越高越好,事务隔离级别设置得越高,意味着势必要花手段去加锁用以保证事务的正确性,那么效率就要降低,因此实际开发中往往要在效率和并发正确性之间做一个取舍,一般情况下会设置为READ_COMMITED,此时避免了脏读,并发性也还不错,之后再通过一些别的手段去解决不可重复读和幻读的问题就好了。

四、Spring JDBC

  • Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发

1、导入JAR

<dependencies>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-jdbc</artifactId>
		<version>4.2.5.RELEASE</version>
		<scope>compile</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-tx</artifactId>
		<version>4.2.5.RELEASE</version>
		<scope>compile</scope>
	</dependency>
	<!-- 获取上下文 -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>4.2.5.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>com.mchange</groupId>
		<artifactId>c3p0</artifactId>
		<version>0.9.5.2</version>
	</dependency>
	<!-- 连接到mysql -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.35</version>
	</dependency>
	<!-- 单元测试 -->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.10</version>
		<scope>test</scope>
	</dependency>
</dependencies>

2、配置JdbcTemplate

1、配置XML文件

此处使用的是C3P0连接池,可以换成Druid

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <!-- 导入资源文件
        读取db.properties文件中的数据 -->
    <context:property-placeholder location="classpath:db.properties"/>

    <!-- 配置C3P0数据源 -->
    <bean id="dataSource"
        class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
        <property name="driverClass" value="${jdbc.driverClass}"></property>

        <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
        <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
    </bean>

    <!-- 配置Spring的jdbcTemplate 
        并注入一个dataSource数据源-->
    <bean id="jdbcTemplate"
        class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>    
    </bean>
</beans>

2、代码实现

public class JDBCUtils {
    private static DateSource dateSource = null;

    static {
        try {
            InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            properties.load(in);

            dataSource.setUrl(properties.getProperty("url"));
            dataSource.setDriverClassName(properties.getProperty("driver")); //这个可以缺省的,会根据url自动识别
            dataSource.setUsername(properties.getProperty("username"));
            dataSource.setPassword(properties.getProperty("password"));

            //下面都是可选的配置
            dataSource.setInitialSize(10);  //初始连接数,默认0
            dataSource.setMaxActive(30);  //最大连接数,默认8
            dataSource.setMinIdle(10);  //最小闲置数
            dataSource.setMaxWait(2000);  //获取连接的最大等待时间,单位毫秒
            dataSource.setPoolPreparedStatements(true); //缓存PreparedStatement,默认false
            dataSource.setMaxOpenPreparedStatements(20); //缓存PreparedStatement的最大数量,默认-1(不缓存)。大于0时会自动开启缓存PreparedStatement,所以可以省略上一句代码
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static JdbcTemplate getJdbcTemplate() {
        return new JdbcTemplate(dateSource);
    }

    public static void release(Connection connection, Statement statement, ResultSet resultSet)	   {
        if(connection != null){
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if(statement != null){
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (resultSet != null){
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

}

3、使用JdbcTemplate

1、update()

  • 执行DML语句。增删改语句

  • 执行插入语句有int类型的返回值

//private JdbcTemplate jdbcTemplate = JDBCUtils.getJdbcTemplate();
@AutoWired
private JdbcTemplate jdbcTemplate;

@Test
//修改指定num的name
public void testUpdate() {
    String sql = "update student set name = ? where num = ?";
    jdbcTemplate.update(sql, "pink",0001);
    System.out.println("success");
}

2、batchUpdate批量更新

//private JdbcTemplate jdbcTemplate = JDBCUtils.getJdbcTemplate();
@AutoWired
private JdbcTemplate jdbcTemplate;

/*
 *批量更新:批量 insert,update,delete
 */
@Test
public void testBatechUpdate() {
    String sql = "insert into student(num,password,name,age,score) value(?,?,?,?,?)";
    List<Object[]> batchArgs = new ArrayList<Object[]>();
    batchArgs.add(new Object[] {"007","123","pojp",23,99});
    batchArgs.add(new Object[] {"008","123","trtp",23,99});
    batchArgs.add(new Object[] {"009","123","QQQp",23,99});
    jdbcTemplate.batchUpdate(sql, batchArgs);
}

3、queryForObject查询单行

  • 查询结果,将结果封装为对象

  • 一般用于聚合函数的查询

/*
 *从数据库中获取一条记录,实际是得到对应的一个对象 
 *RowMapper:行的映射
 *Spring 2.5 提供了一个便利的RowMapper实现-----BeanPropertyRowMapper
 *它可自动将一行数据映射到指定类的实例中 它首先将这个类实例化,然后通过名称匹配的方式,映射到属性中去。
 *字段                                  bean属性
 *USER_NAME 		--> 				userName
 *USER_ID   --> userId
 */
@Test
public void testQueryForObject() {
    String sql = "select num,name,age from student where id = ?";
    RowMapper<stu> rowMapper = new BeanPropertyRowMapper<stu>(stu.class);
    stu s = jdbcTemplate.queryForObject(sql, rowMapper,5);//最后一个参数为id值
    System.out.println(s);
}

4、queryForObject单值查询

/**
 * 获取单个列的值,或统计
 */
@Test
public void testQueryObjectqqq() {
    String sql = "select count(name) from student";
    Long count = jdbcTemplate.queryForObject(sql, Long.class);
    System.out.println(count);
}

5、query查询多行

/*
 *查询实体类的集合 
 */
@Test
public void testQueryForList() {
    String sql = "select num,name,age from student where id > ?";
    RowMapper<stu> rowMapper = new BeanPropertyRowMapper<stu>(stu.class);
    List<stu> s = jdbcTemplate.query(sql, rowMapper,0);//最后一个参数为id值
    System.out.println(s);
}

6、queryForList():查询结果将结果集封装为list集合

  • 将每一条记录封装为一个Map集合,再将Map集合装载到List集合中

7、queryForMap():查询结果将结果集封装为map集合

  • 这个方法查询的结果集长度只能是1,将列名作为key,将值作为value,将这条记录封装为一个Map集合

五、使用数据库连接池

1、C3P0数据库连接池

1、代码实现

public class JdbcUtils_C3P0 {
    
	private static ComboPooledDataSource ds = null;
    
	static{
		try{
			ds = new ComboPooledDataSource();
			ds.setDriverClass("com.mysql.jdbc.Driver");
			ds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbcstudy");
			ds.setUser("root");
			ds.setPassword("521216");
			
			ds.setInitialPoolSize(10);//最初连接数
			ds.setMinPoolSize(5);//最小连接数
			ds.setMaxPoolSize(20);//最大连接数
			
		}catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
	}
	
	public static Connection getConnection() throws SQLException{
		return ds.getConnection();
	}
	
	public static void release(Connection conn,Statement st,ResultSet rs){
		if(rs!=null){
			try{
				rs.close();
			}catch (Exception e) {
				e.printStackTrace();
			}
			rs = null;
		}
        
		if(st!=null){
			try{
				st.close();
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		if(conn!=null){
			try{
				conn.close();
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
}

2、使用配置文件(src下):c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<default-config>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy</property>
		<property name="user">root</property>
		<property name="password">521216</property>
	
		<property name="acquireIncrement">5</property>
		<property name="initialPoolSize">10</property>
		<property name="minPoolSize">5</property>
		<property name="maxPoolSize">20</property>
	</default-config>
	
	<named-config name="mysql">
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy</property>
		<property name="user">root</property>
		<property name="password">521216</property>
	
		<property name="acquireIncrement">5</property>
		<property name="initialPoolSize">10</property>
		<property name="minPoolSize">5</property>
		<property name="maxPoolSize">20</property>
	</named-config>
	
	
	<named-config name="oracle">
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy</property>
		<property name="user">root</property>
		<property name="password">521216</property>
	
		<property name="acquireIncrement">5</property>
		<property name="initialPoolSize">10</property>
		<property name="minPoolSize">5</property>
		<property name="maxPoolSize">20</property>
	</named-config>
</c3p0-config>
//JdbcUtils_C3P0可以改成:
	/*
		ds = new ComboPooledDataSource();
		ds.setDriverClass("com.mysql.jdbc.Driver");
		ds.setJdbcUrl("jdbc:mysql://localhost:3306/day16");
		ds.setUser("root");
		ds.setPassword("root");

		ds.setInitialPoolSize(10);//最初连接数
		ds.setMinPoolSize(5);//最小连接数
		ds.setMaxPoolSize(20);//最大连接数
	*/
	ds = new ComboPooledDataSource("mysql");//如果默认()

2、Druid数据库连接池

1、纯代码方式

		//数据源配置
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl("jdbc:mysql://127.0.0.1/db_student?serverTimezone=UTC");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); //这个可以缺省的,会根据url自动识别
        dataSource.setUsername("root");
        dataSource.setPassword("521216");
        
        //下面都是可选的配置
        dataSource.setInitialSize(10);  //初始连接数,默认0
        dataSource.setMaxActive(30);  //最大连接数,默认8
        dataSource.setMinIdle(10);  //最小闲置数
        dataSource.setMaxWait(2000);  //获取连接的最大等待时间,单位毫秒
        dataSource.setPoolPreparedStatements(true); //缓存PreparedStatement,默认false
        dataSource.setMaxOpenPreparedStatements(20); //缓存PreparedStatement的最大数量,默认-1(不缓存)。大于0时会自动开启缓存PreparedStatement,所以可以省略上一句代码

        //获取连接
        Connection connection = dataSource.getConnection();

        //Statement接口
        Statement statement = connection.createStatement();
        String sql1 = "insert into tb_student (name,age) values ('chy',20)";
        statement.executeUpdate(sql1);

        //PreparedStatement接口
        String sql2 = "insert into tb_student (name,age) values ('chy',21)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql2);
        preparedStatement.execute();

        //关闭连接
        connection.close();

2、配置文件方式

1、在sources下新建druid.properties

url=jdbc:mysql://127.0.0.1/db_student?serverTimezone=UTC
#这个可以缺省的,会根据url自动识别
driverClassName=com.mysql.cj.jdbc.Driver
username=root
password=abcd

##初始连接数,默认0
initialSize=10
#最大连接数,默认8
maxActive=30
#最小闲置数
minIdle=10
#获取连接的最大等待时间,单位毫秒
maxWait=2000
#缓存PreparedStatement,默认false
poolPreparedStatements=true
#缓存PreparedStatement的最大数量,默认-1(不缓存)。大于0时会自动开启缓存PreparedStatement,所以可以省略上一句设置
maxOpenPreparedStatements=20

2、使用

public class Test {
    
    public static void main(String[] args) throws Exception {
        //数据源配置
        Properties properties=new Properties();
        //通过当前类的class对象获取资源文件
        InputStream is = Test.class.getResourceAsStream("/druid.properties"); 
        properties.load(is);
        //返回的是DataSource,不是DruidDataSource
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

        //获取连接
        Connection connection = dataSource.getConnection();

        //Statement接口
        Statement statement = connection.createStatement();
        String sql1 = "insert into tb_student (name,age) values ('chy',20)";
        statement.executeUpdate(sql1);

        //PreparedStatement接口
        String sql2 = "insert into tb_student (name,age) values ('chy',22)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql2);
        preparedStatement.execute();

        //关闭连接
        connection.close();
    }
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值