jdbc操作数据库学习

jdbc编程的步骤大致分为:

1.加载数据库驱动,首先对于不同的数据库要导入其相应的jar包,我这里是mysql数据库,可直接在eclipse中建立maven项目,在maven中导入其对应的jar包

以下为加载jdbc驱动

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

2.通过DriverManager获取数据库连接

其中第一个参数为mysql地址和其对应的端口(当然如果有服务器也可以使用服务器的公网ip和mysql的端口),第二个参数和第三个参数为mysql的用户名和密码

Connection conn = DriverManager.getConnection(
					"jdbc:mysql://127.0.0.1:3306/class",
					"root","123456"
				);

3.通过Statement对象执行sql语句,可通过Connection创建Statement对象

Statement stmt = conn.createStatement();

学过mysql的都知道sql语句分为

1、数据操纵语言(DML):用来操纵数据库中数据的命令。包括:select、insert、update、delete。 2、数据定义语言(DDL):用来建立数据库、数据库对象和定义列的命令。包括:create、alter、drop。 3、数据控制语言(DCL):用来控制数据库组件4.数据库查询语言(DQL):用来查询数据库
其中对于DML语言

执行DML时使用executeUpdate(sql)返回受影响的行数

执行DQL时使用executeQuery(sql)返回一个ResultSet对象,ResultSet中的next()方法使结果集的指针指向下一行,ResultSet结果集的指针默认指向第一行

ResultSet s = stmt.executeQuery("select languages.*"+"from languages"
					);
			while(s.next()) {
				System.out.println(s.getInt(1)+"\t"+s.getString(2));
			}
方法getInt(1)表示获取第一列的数据,当然你如果知道列名也可以用列名做参数

执行DDL时使用 使用execute 返回类型为Boolean类型 表示执行该sql后是否返回ResultSet结果集 如果有 可以调getResultSet来返回ResultSet对象,getUpdateCount返回受影响的行数

使用PreparedStatement执行sql语句,在执行sql语句时,数据库都会根据sql语句来创建新的执行计划,如果反复执行类似的sql语句,必定会降低数据库的执行效率,所以使用预编译的sql语句可大大提高数据库效率,同时PreparedStatement还可有效的防止sql注入

PreparedStatement pstm = conn.prepareStatement("insert into jdbc_test values(null,?,1);");
		pstm.setString(1, "ruby");
		pstm.executeUpdate();

使用ResultSetMeteData分析结果集

//得到RsesultSetMetaData对象
		ResultSetMetaData rd = rs.getMetaData();
		//获取列的数量
		int col_number = rd.getColumnCount();
		System.out.println("列的数量为"+col_number);
		//获取指定索引的列名与列的类型
		for(int i = 1;i < col_number;i++) {
			System.out.println("索引"+i+"的列名:"+rd.getColumnName(i)+"类型:"+rd.getColumnTypeName(i));
		}

使用数据库池管理连接:

数据库每次创建连接都会消耗一定的时间,使用数据库连接池的好处就是当用户不使用连接是,把连接保存起来,给下一个用户使用,从而提高数据库使用效率

BasicDataSource ds = new BasicDataSource();
		ds.setDriverClassName(driver);
		ds.setUrl(url);
		ds.setUsername(user);
		ds.setPassword(pass);
		ds.setInitialSize(2);
		ds.setMaxActive(100);
		//使用连接池中的数据库连接
		Connection conn = ds.getConnection();
		String sql = "select * from languages";
		Statement st = conn.createStatement();
		ResultSet rs = st.executeQuery(sql);

封装

为了使用jdbc的效率,不能每次都写加载数据等一些重复的工作

所以我们可以写一个工具类,提供一些方法来获取和关闭连接

我这里以数据库连接池为例

import org.apache.commons.dbcp.BasicDataSource;

/**
 * 使用连接池技术管理数据库连接
 * 
 * @author Administrator
 *
 */
public class DButil2 {
	// 数据库连接池
	private static BasicDataSource ds;
	// 为不同线程管理连接
	private static ThreadLocal<Connection> tl;

	static {
		try {
			Properties prop = new Properties();

			// InputStream is =
			// DButil2.class.getClassLoader().getResourceAsStream("day01/config.properties");
			FileInputStream is = new FileInputStream("C:\\Users\\Administrator\\Desktop\\mysql.ini");
			prop.load(is);
			is.close();
			System.out.println("k");
			// 初始化连接池

			ds = new BasicDataSource();
			// 设置驱动 (Class.forName())
			ds.setDriverClassName(prop.getProperty("driver"));
			// 设置url
			ds.setUrl(prop.getProperty("url"));
			// 设置数据库用户名
			ds.setUsername(prop.getProperty("user"));
			// 设置数据库密码
			ds.setPassword(prop.getProperty("pwd"));
			// 初始连接数量
			ds.setInitialSize(Integer.parseInt(prop.getProperty("initsize")));
			// 连接池允许的最大连接数
			ds.setMaxActive(Integer.parseInt(prop.getProperty("maxactive")));
			// 设置最大等待时间
			// ds.setMaxWait(Integer.parseInt(prop.getProperty("maxwait")));
			// // 设置最小空闲数
			// ds.setMinIdle(Integer.parseInt(prop.getProperty("minidle")));
			// // 设置最大空闲数
			// ds.setMaxIdle(Integer.parseInt(prop.getProperty("maxidle")));
			// // 初始化线程本地
			tl = new ThreadLocal<Connection>();
			System.out.println("k");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取数据库连接
	 * 
	 * @throws SQLException
	 */
	// String sql = "select * from languages";

	public static Connection getConnection() {
		/*
		 * 通过连接池获取一个空闲连接
		 */
		try {
			Connection conn = ds.getConnection();
			return conn;
		} 
		catch (Exception e) {
			//System.out.println("j");
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		// tl.set(conn);
	
	
	}

	/**
	 * 关闭数据库连接
	 */
	public static void closeConnection(Connection conn) {
		try {

			if (conn != null) {
				/*
				 * 通过连接池获取的Connection 的close()方法实际上并没有将 连接关闭,而是将该链接归还。
				 */
				conn.close();

			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

数据库事物

我们知道数据库的修改表上的数据时是自动提交 保存  如果表上的数据被改动,没有经过提交保存就再次改就会抛出异常 以下是一个例子

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

import day01.DBUtil2;

/**
 * 与用户相关的业务逻辑
 * 
 * @author Administrator
 *
 */
public class UserService {
	public static void main(String[] args) {
		/*
		 * 程序启动后: 选择1,2,3,4等操作 1:注册新用户 用户ID从1开始 2:更改用户信息 3:删除用户信息 4:查询用户信息
		 */
		System.out.println("请输入选项:");
		System.out.print("1:注册  ");
		System.out.print("2:登录  ");
		System.out.print("3:修改  ");
		System.out.print("4:删除  ");
		System.out.println("5:查询  ");
		System.out.println("6:转账  ");
		Scanner scanner = new Scanner(System.in);
		int option = Integer.parseInt(scanner.nextLine().trim());

		switch (option) {
		case 1:
			// 注册
			regUser(scanner);
			break;
		case 2:
			// 登录
			login(scanner);
			break;
		case 3:
			break;
		case 4:
			break;
		case 5:
			break;
		case 6:
			giveMoney(scanner);
			break;
		}
	}

	/**
	 * 转账操作
	 * 
	 * @param scanner
	 */
	public static void giveMoney(Scanner scanner) {
		/*
		 * 1:获取用户输入的信息 2:必要的验证,看看转出账户余额是否够 --事务开始的地方 3:更新转出账户的余额 4:更新转入账户的余额 --提交事务的地方
		 */
		System.out.println("现在是转账操作");
		System.out.println("请输入您的账号");
		String fromUser = scanner.nextLine().trim();

		System.out.println("请输入收款人的账号");
		String toUser = scanner.nextLine().trim();

		System.out.println("请输入转出金额");
		String money = scanner.nextLine().trim();

		// 2
		String countSql = "SELECT money " + "FROM user_fanchuanqi " + "WHERE name='" + fromUser + "'";
		try {
			Connection conn = DBUtil2.getConnection();
			// 关闭自动提交事务
			conn.setAutoCommit(false);
			Statement state = conn.createStatement();
			ResultSet rs = state.executeQuery(countSql);
			// 判断是否查询出数据
			if (rs.next()) {
				int count = rs.getInt(1);
				// 判断余额是否足够
				if (count >= Integer.parseInt(money)) {
					// 执行转账操作
					// 开始纳入事务控制,因为开始执行DML操作了
					String fromSql = "UPDATE user_fanchuanqi " + "SET money=money-" + money + " " + "WHERE name='"
							+ fromUser + "'";
					// 修改当前用户的余额
					if (state.executeUpdate(fromSql) > 0) {

						// 修改收款人的余额
						String toSql = "UPDATE user_fanchuanqi " + "SET money=money+" + money + " " + "WHERE name='"
								+ toUser + "'";
						if (state.executeUpdate(toSql) > 0) {
							System.out.println("转账成功");
							/*
							 * 两次更新账户操作均成功,我们才 认为这次转账操作完毕。提交事务
							 */
							conn.commit();
						} else {
							System.out.println("转账失败:没有收款人" + toUser);
							/*
							 * 若第二次更新操作失败,那么整次 操作就算作失败。应该回滚事务。
							 */
							conn.rollback();
						}
					}
				} else {
					System.out.println("余额不足");
				}
			} else {
				System.out.println("没有该用户:" + fromUser);
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			DBUtil2.closeConnection();
		}
	}

	/**
	 * 登录操作
	 * 
	 * @param scanner
	 */
	public static void login(Scanner scanner) {
		/*
		 * 1:要求用输入用户名及密码 2:根据用户输入作为条件去表中查询 3:若查询出数据,说明输入正确
		 */
		System.out.println("现在是登录操作");
		System.out.println("请输入用户名:");
		String user = scanner.nextLine().trim();
		System.out.println("请输入密码:");
		String pwd = scanner.nextLine().trim();

		try {
			Connection conn = DBUtil2.getConnection();

			String sql = "SELECT * FROM user_fanchuanqi " + "WHERE name=? AND password=?";

			PreparedStatement ps = conn.prepareStatement(sql);

			ps.setString(1, user);
			ps.setString(2, pwd);

			ResultSet rs = ps.executeQuery();
			// 根据用户输入的能否查到数据
			if (rs.next()) {
				System.out.println("登录成功!");
			} else {
				System.out.println("用户名或密码错误!");
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			DBUtil2.closeConnection();
		}

	}

	/**
	 * 注册操作
	 * 
	 * @param scanner
	 */
	public static void regUser(Scanner scanner) {
		/*
		 * 若是注册操作: 1:获取用户输入的相关信息 2:获取连接 3:获取Statement 4:先获取id的最大值 5:对该值+1,作为当前记录的主键值
		 * 6:插入记录 7:关闭连接
		 */
		try {
			// 1
			System.out.println("现在是注册操作:");
			System.out.println("请输入用户名:");
			String user = scanner.nextLine().trim();
			System.out.println("请输入密码:");
			String pwd = scanner.nextLine().trim();
			System.out.println("请输入账户金额:");
			String money = scanner.nextLine().trim();
			System.out.println("请输入邮箱:");
			String email = scanner.nextLine().trim();

			// 2
			Connection conn = DBUtil2.getConnection();

			// 3
			Statement state = conn.createStatement();

			// 4
			String idSql = "SELECT MAX(id) id FROM user_fanchuanqi";

			// 5
			ResultSet rs = state.executeQuery(idSql);

			int id = -1;
			if (rs.next()) {
				id = rs.getInt("id");
			}
			// 统计出最大值后,对ID加1
			id++;
			rs.close();

			// 6
			/*
			 * INSERT INTO user_fanchuanqi VALUES(1,'jack','1234',5000,'[email protected]')
			 * 
			 */
			String sql = "INSERT INTO user_fanchuanqi " + "VALUES" + "(" + id + "," + "'" + user + "'," + "'" + pwd
					+ "'," + "" + money + "," + "'" + email + "'" + ")";
			System.out.println(sql);
			if (state.executeUpdate(sql) > 0) {
				System.out.println("注册成功!欢迎你:" + user);
			} else {
				System.out.println("呵呵");
			}
			DBUtil2.closeConnection();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

批量更新数据

/**
 * 使用批处理批量更新数据
 * @author Administrator
 *
 */
public class BatchDemo {
	public static void main(String[] args){
		try{
			Connection conn
				= DBUtil2.getConnection();
			Statement state
				= conn.createStatement();
			
			for(int i=1000;i<20000;i++){
				String sql 
					="INSERT INTO user_fanchuanqi " +
					 "(id,name) " +
					 "VALUES" +
					 "("+i+",'test"+i+"')";
				
//				state.executeUpdate(sql);
				//缓存,等待一起执行
				state.addBatch(sql);
				if(i%500==0){
					state.executeBatch();
					state.clearBatch();
				}		
			}
			state.executeBatch();
			
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			DBUtil2.closeConnection();
		}
	}
















猜你喜欢

转载自blog.csdn.net/weixin_41182987/article/details/79771118