JDBC与DAO篇--03 JDBC高级编程、DAO


1.ResultSetMetaData

ResultSetMetaData:数据结果集的元数据

和查询出来的结果集相关,从结果集(ResultSet)中获取。

ResultSetMetaData用于描述列信息

例子:

DbUtils.java:

package com.lcz.jdbc.day03;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import org.apache.commons.dbcp.BasicDataSource;

/**
 * 连接池版本的数据库连接管理工具类
 * 适合于并发场合
 * @author LvChaoZhang
 *
 */
public class DbUtils {
	private static String driver;
	private static String url;
	private static String username;
	private static String password;
	private static int initSize;
	private static int maxActive;
	private static BasicDataSource bs;
	static {
		//连接池
		bs=new BasicDataSource();
		Properties cfg=new Properties();
		try {
			InputStream in =DbUtils.class.getClassLoader().getResourceAsStream("db.properties");
			cfg.load(in);
			//初始化参数
			driver=cfg.getProperty("jdbc.driver");
			url=cfg.getProperty("jdbc.url");
			username=cfg.getProperty("jdbc.user");
			password=cfg.getProperty("jdbc.password");
			initSize=Integer.parseInt(cfg.getProperty("initSize"));
			maxActive=Integer.parseInt(cfg.getProperty("maxActive"));
			in.close();
			//初始化连接池
			bs.setDriverClassName(driver);
			bs.setUrl(url);
			bs.setUsername(username);
			bs.setPassword(password);
			bs.setInitialSize(initSize);
			bs.setMaxActive(maxActive);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public static Connection getConnection() {
		try {
			//getConnection()从连接池中获取重用的连接,如果连接池满了,则等待,如果有连接归还,则获取重用的连接
			Connection conn = bs.getConnection();
			return conn;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
		
	}
	public static void rollback(Connection conn) {
		if(conn!=null) {
			try {
				conn.rollback();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	public static void close(Connection conn) {
		if(conn!=null) {
			try {
				//将用过的连接归还到连接池中
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
package com.lcz.jdbc.day03;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;

/**
 * 结果集
 * @author LvChaoZhang
 *
 */
public class Demo01 {
	public static void main(String[] args) {
		Connection conn=null;
		try {
			conn=DbUtils.getConnection();
			String sql="select * from student";
			Statement st=conn.createStatement();
			ResultSet rs = st.executeQuery(sql);
			
			ResultSetMetaData meta = rs.getMetaData();
			int n=meta.getColumnCount();
			for(int i=1;i<=n;i++) {
				String name=meta.getColumnName(i);
				System.out.println(name);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			DbUtils.close(conn);
		}
	}
}


2.事务(Transaction)

事务:数据库中保证交易可靠的机制

JDBC支持数据库中的事务概念;在JDBC中,事务默认是自动提交的 

事务特性ACID:

1)原子性:事务必须是原子工作单位;对于其数据修改,要么全都执行,要么全都不执行

2)一致性:事务在完成时,必须使所有的数据都保持一致状态。

3)隔离性:由并发事务所作的修改必须与任何其他并发事务所作的修改隔离

4)持久性:事务完成之后,它对于系统的影响是永久性的。

 

 

JDBC事务API

相关API:

Connection.getAutoCommit():获得当前事务的提交方式,默认为true

Connection.setAutoCommit():设置事务的提交属性,参数是true:默认提交;false:不自动提交

Connection.commit():提交事务

 例子:转账

package com.lcz.jdbc.day03;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class Demo2 {
	
	public static void main(String[] args) {
		pay(2,1,1000);
		System.out.println("ok");
	}
	
	public static void pay(int from,int to,double money) {
		Connection conn=null;
		String sql1="update lcz_account set balance=balance+? where id=?";
		String sql2="select balance from lcz_account where id=?";
		try {
			conn=DbUtils.getConnection();
			conn.setAutoCommit(false);
			PreparedStatement ps = conn.prepareStatement(sql1);
			//减钱
			ps.setDouble(1, -money);
			ps.setInt(2, from);
			int n=ps.executeUpdate();
			if(n!=1) {
				throw new Exception("扣错了");
			}
			//增钱
			ps.setDouble(1, money);
			ps.setInt(2, to);
			n=ps.executeUpdate();
			if(n!=1) {
				throw new Exception("加错了");
			}
			ps.close();
			//检查
			ps=conn.prepareStatement(sql2);
			ps.setInt(1, from);
			ResultSet rs = ps.executeQuery();
			while(rs.next()) {
				double bal=rs.getDouble("balance");
				if(bal<0) {
					throw new Exception("原账号透支");
				}
			}
			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
			DbUtils.rollback(conn);
		}finally {
			DbUtils.close(conn);
		}
	}
}

3.批量更新

addBatch(String sql):Statement类的方法,可以将多条sql语句添加Statement的SQL语句列表中。

addBatch():PreparedStament类的方法,可以将多条预编译的sql语句添加到PreparedStatement对象的SQL语句列表中。

executeBatch():把Statement对象或PreparedStatement对象语句列表中的所有SQL语句发送给数据库进行处理。

clearBatch():清空当前SQL语句列表

 

防止OutOfMemory:如果PreparedStatement对象中的SQL列表包含过多的待处理的SQL语句会产生OutOfMemeory错误,分段处理SQL语句列表。

 例子:批量处理DDL

package com.lcz.jdbc.day03;

import java.sql.Connection;
import java.sql.Statement;

/**
 * 执行一批DDL
 * @author LvChaoZhang
 *
 */
public class Demo03 {
	public static void main(String[] args) {
//		String sql1="create table log_01(id int(8),msg varchar(100))";
//		String sql2="create table log_02(id int(8),msg varchar(100))";
//		String sql3="create table log_03(id int(8),msg varchar(100))";
		String sql1="insert  log_01(id,msg) values(1,'I')";
		String sql2="insert  log_02(id,msg) values(2,'LOVE')";
		String sql3="insert  log_03(id,msg) values(3,'U')";
		//执行一批SQL
		Connection conn=null;
		try {
			conn=DbUtils.getConnection();
			Statement st=conn.createStatement();
			//sql1添加到statement的缓冲区
			st.addBatch(sql1);
			st.addBatch(sql2);
			st.addBatch(sql3);
			//执行一批SQL
			int[] arr = st.executeBatch();
			System.out.println("OK");
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			DbUtils.close(conn);
		}
	}
}

例子:执行批量参数处理

package com.lcz.jdbc.day03;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Arrays;

/**
 * 执行批量参数处理
 * @author LvChaoZhang
 *
 */
public class Demo04 {
	public static void main(String[] args) {
		String sql="insert into user(id,name,pwd) values(?,?,?)";
		Connection conn=null;
		try {
			conn=DbUtils.getConnection();
			PreparedStatement ps = conn.prepareStatement(sql);
			for(int i=0;i<100;i++){
			//替换参数
				ps.setInt(1, i);
				ps.setString(2, "name"+i);
				ps.setString(3, "123456");
				//将参数添加到缓冲区
				ps.addBatch();
				//防止OutOfMemory
				if((i+1)%8==0) {
					ps.executeBatch();
					ps.clearBatch();
				}
			}
			//批量执行
			int[] arr = ps.executeBatch();
			System.out.println(Arrays.toString(arr));
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			DbUtils.close(conn);
		}
	}
}

4.返回自动主键

 

package com.lcz.jdbc.day03;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
 * 数据库中
 * 
 * @author LvChaoZhang
 *
 */
public class Demo5 {
	public static void main(String[] args) {
		Connection conn=null;
		try {
			conn=DbUtils.getConnection();
			conn.setAutoCommit(false);
			//第一个sql
			String sql1="insert into r_keywords(word) values(?)";
			String[] cols= {"id"};//自动生成序号的列名
			PreparedStatement ps = conn.prepareStatement(sql1,cols);
			ps.setString(1, "雾霾");
			int n = ps.executeUpdate();
			if(n!=1) {
				throw new Exception("话题添加失败");
			}
			//获取自动生成的ID
			ResultSet rs = ps.getGeneratedKeys();
			int id=-1;
			
			while(rs.next()) {
				id=rs.getInt(1);
			}
			//第二个sql
			String sql2="insert into r_post(content,k_id) values(?,?)";
			ps=conn.prepareStatement(sql2);
			ps.setString(1, "今天天气不错,晚上有雾霾");
			ps.setInt(2,id);
			n = ps.executeUpdate();
			if(n!=1) {
				throw new Exception("天气太糟");
			}
			conn.commit();
			System.out.println("ok");
		} catch (Exception e) {
			e.printStackTrace();
			DbUtils.rollback(conn);
		}finally {
			DbUtils.close(conn);
		}
	}
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mind_programmonkey

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值