第七章. Java 数据库编程

Java 数据库编程

1. 数据库概论

见数据库专栏


2. JDBC基本操作

2.1 JDBC

Java和数据库是平行的两套系统
Java和数据库的连接方法

  • JDBC (主流): Java Database Connectivity
    – JDBC 1, JDK 1.1
    – JDBC 2 JDK 1.3~JDK1.4
    – JDBC 3 JDK 5
    – JDBC 4 JDK 6, (JDK 7, JDBC4.1; JDK8, JDBC4.2)

2.2 JDBC 操作

java.sql., javax.sql.: 这2个包只是接口类
– 根据数据库版本和JDBC版本合理选择
– 一般数据库发行包都会提供jar包,同时也要注意区分32位
和64位(数据库分32/64位, JDK也分32/64位)。

连接字符1串(数据库连接)
– jdbc:oracle:thin:@127.0.0.1:1521:dbname
– jdbc:mysql://localhost:3306/mydb
– jdbc:sqlserver://localhost:1433; DatabaseName=dbname

Java连接数据库操作步骤:

  1. 构建连接(搭桥)
    – 注册驱动,寻找材质, class.forName(“…”); //Oracle,Mysql ,SQL server…
    – 确定对岸目标 , 建桥 Connection
  2. 执行操作(派个人过桥, 提着篮子,去拿数据)
    – Statement (执行者)
    – ResultSet(结果集)
  3. 释放连接(拆桥)
    – connection.close();

Statement :执行操作

  • Statement 执行者类
    – 使用executeQuery()执行select语句,返回结果放在ResultSet
    – 使用executeUpdate()执行insert/update/delete,返回修改的行数
    – 一个Statement对象一次只能执行一个命令
  • ResultSet 结果对象
    – next() 判断是否还有下一条记录
    – getInt/getString/getDouble/……
    • 可以按索引位置,可以按照列名

注意事项:

  • ResultSet不能多个做笛卡尔积连接
  • ResultSet最好不要超过百条,否则极其影响性能
  • ResultSet也不是一口气加载所有的select结果数据
  • Connection 很昂贵,需要及时close
  • Connection所用的jar包和数据库要匹配

JDBC的查找,更新:

import java.sql.*;

public class SelectTest {
    public static void main(String[] args){
    	
    	//构建Java和数据库之间的桥梁介质
        try{            
            Class.forName("com.mysql.jdbc.Driver");
            System.out.println("注册驱动成功!");
        }catch(ClassNotFoundException e1){
            System.out.println("注册驱动失败!");
            e1.printStackTrace();
            return;
        }
        
        String url="jdbc:mysql://localhost:3306/test";  //localhost为IP地址      
        Connection conn = null;
        try {
        	//构建Java和数据库之间的桥梁:URL,用户名,密码
            conn = DriverManager.getConnection(url, "root", "123456");
            
            //构建数据库执行者
            Statement stmt = conn.createStatement(); 
            System.out.println("创建Statement成功!");      
            
            //执行SQL语句并返回结果到ResultSet
            ResultSet rs = stmt.executeQuery("select bookid, bookname, price from book order by bookid");
                        
            //开始遍历ResultSet数据
            while(rs.next())
            {
            	System.out.println(rs.getInt(1) + "," + rs.getString(2) + "," + rs.getInt("price"));
            }
            
            rs.close();
            stmt.close();
            
        } catch (SQLException e){
            e.printStackTrace();
        }
        finally
        {
        	conn.close();
        }
        	
}

在这里插入图片描述


3. JDBC高级操作

3.1 事务

数据库事务(Database Transaction):

  • 数据库运行中的逻辑工作单位,执行的一系列操作,要么完全地执行,要么完全地不执行。
  • 必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性

JDBC事务:

  • 关闭自动提交,实现多语句同一事务:
    – connection.setAutoCommit(false);
  • connection.commit(); 提交事务
  • connection.rollback(); 回滚事务
  • 保存点机制
    – connection.setSavepoint()
    – connection.rollback(Savepoint)

执行部分:

public static void insertBook(Connection conn, String sql) {
		try {
			// 构建数据库执行者
			Statement stmt = conn.createStatement();
			// 执行SQL语句
			int result = stmt.executeUpdate(sql);
			stmt.close();

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


		try {
			// 构建Java和数据库之间的桥梁:URL,用户名,密码
			conn = DriverManager.getConnection(url, "root", "123456");
			conn.setAutoCommit(false);//取消自动提交

			insertBook(conn, "insert into t_book values(101, 'aaaa', 10)");
			insertBook(conn, "insert into t_book values(102, 'bbbb', 10)");
			insertBook(conn, "insert into t_book values(103, 'cccc', 10)");
			Savepoint phase1 = conn.setSavepoint(); //设置一个保存点
			insertBook(conn, "insert into t_book values(104, 'cccc', 10)");
			insertBook(conn, "insert into t_book values(105, 'cccc', 10)");
			conn.rollback(phase1);  //回滚到phase1保存点,即上面2行无效
			conn.commit();

			System.out.println("操作成功");

		}

运行结果:
在这里插入图片描述

3.2 PreparedStatement

Java提供PreparedStatement :进行SQL语句的拼接,传参

  • 使用“?” 代替字符串拼接
  • 使用setXXX(int,Object)的函数来实现对于“?”的替换
  • 提供addBatch批量更新功能
    –只提交,不执行
    –当有大量sql语句结构相同,仅有值不同时,可以通过addBatch操作提高性能
try {
        	//构建Java和数据库之间的桥梁:URL,用户名,密码
            conn = DriverManager.getConnection(url, "root", "123456");
            //三个问号分别对应括号的bookid,bookname,price(形参)
            String sql = "insert into t_book(bookid,bookname,price) values(?,?,?)";
            
            //构建数据库执行者
            PreparedStatement pstmt = conn.prepareStatement(sql);
            
            //执行SQL语句
            int bookid = 10;
            String bookName = "Effective Java',50);delete from t_book;insert into t_book values(101, 'faked book";
            int price = 50;
            
            //values(1, 'Effective Java', 50)
            String bookName = "aaaaaaaaaaaaaaaa";
            int price = 50;
            
            //values(1, 'Effective Java', 50)
            for(int i=200;i<210;i++)
            {
            	pstmt.setInt(1, i);
                pstmt.setString(2, bookName);
                pstmt.setInt(3, price);
                pstmt.addBatch();//只提交,不执行
            }            
            
            pstmt.executeBatch();
            int result = pstmt.executeUpdate(); //执行
                        
            pstmt.close();
            
            System.out.println("操作成功");
            
        }

3.3 ResultSetMetaData

  1. ResultSet可以用来承载所有的select语句返回的结果集
  2. ResultSetMetaData来获取ResultSet返回的属性(如,每一行
    的名字类型等)
    – getColumnCount(),返回结果的列数
    – getColumnName(), 返回第i列列名
    – getColumnClassName(i),返回第i列的数据的Java类名
    – getColumnTypeName(i),返回第i列的数据库类型名称
    – getColumnType(i),返回第i列的SQL类型
    – …
			ResultSet rs = stmt.executeQuery("select bookid, bookname, price from t_book order by bookid");
                        
      		//获取结果集的元数据
            ResultSetMetaData meta = rs.getMetaData(); 
            int cols = meta.getColumnCount(); 
            for(int i=1;i<=cols;i++)
            {
            	System.out.println(meta.getColumnName(i) + "," + meta.getColumnTypeName(i));
            }

4. 数据库连接池

:构建连接与断开连接的成本很高

  • 运用共享技术来实现数据库连接池(享元模式)
    – 降低系统中数据库连接Connection对象的数量
    – 降低数据库服务器的连接响应消耗
    – 提高Connection获取的响应速度

数据库连接池

  • 理解池Pool的概念
    – 初始数、最大数、增量、超时时间等参数。
  • 常用的数据库连接池
    – DBCP (Apache, http://commons.apache.org/,性能较差)
    – C3P0 (https://www.mchange.com/projects/c3p0/)
    – Druid (Alibaba, https://github.com/alibaba/druid) //性能最好

    • driverClass: 驱动class,这里为mysql的驱动
    • jdbcUrl: jdbc链接
    • user password:数据库用户名,密码
    • initialPoolSize 初始数量:一开始创建多少条链接
    • maxPoolSize 最大数:最多有多少条链接
    • acquireIncrement 增量:用完每次增加多少个
    • maxIdleTime最大空闲时间:超出的链接会被抛弃
  • 数据库连接池是对connection进行管理,而不是产生,产生要通过Mysql.Driver

Druid连接的获取:

conn = DruidFactory1.getConnection(); //工厂模式1
conn = DruidFactory2.getConnection(); //工厂模式2

Druid工厂模式1:在Java文件中配置初始化信息

public class DruidFactory1 {
	private static DruidDataSource dataSource = null;

	public static void init() throws Exception {
		
		dataSource = new DruidDataSource();
		dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 
		dataSource.setUsername("root");
		dataSource.setPassword("123456");
		dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test"); 
		dataSource.setInitialSize(5);
		dataSource.setMinIdle(1); 
		dataSource.setMaxActive(10); 
		// 启用监控统计功能 dataSource.setFilters("stat");// 
	}
	
	public static Connection getConnection() throws Exception {
		if(null == dataSource)
		{
			init();
		}
        return dataSource.getConnection();
    }
}

Druid工厂模式2:通过Properties文件进行配置:

public class DruidFactory2 {
	private static DruidDataSource dataSource = null;

	public static void init() throws Exception {
		Properties properties = new Properties();
		
		InputStream in = DruidFactory2.class.getClassLoader().getResourceAsStream("druid.properties");  
		properties.load(in); 		
		dataSource = (DruidDataSource)DruidDataSourceFactory.createDataSource(properties);		
		
		in.close();
	}
	
	public static Connection getConnection() throws Exception {
		if(null == dataSource)
		{
			init();
		}
        return dataSource.getConnection();
    }
}

Properties文件:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值