JDBC知识点
JDBC
JDBC驱动程序
数据库配置信息
url:连接数据库系统资源描述符 jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8
DriverClass:数据库系统驱动名称
UserName:数据库系统用户名称
PassWord:登录数据库系统用户密码
others:其他信息
## 数据库属性配置信息
## 连接数据库服务器URL
jdbc_url = jdbc:mysql://localhost:3306/ATMSYSTEM?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC
## 连接数据库服务器驱动类
jdbc_driver = com.mysql.jdbc.Driver
## 访问数据库服务器用户名称
jdbc_UserName = root
## 访问数据库服务器用户密码
jdbc_PassWord = 123456
步骤
- 加载驱动 Class.forName(“com.mysql.jdbc.Driver”);
- 连接数据库 DriverManger.getConnection(); 返回Connection对象
- 执行SQL对象 调用createStatement() 返回Statement对象
- 调用executeQuery(sql) 执行sql语句
try {
Class.forName("com.mysql.cj.jdbc.Driver"); //加载驱动
String url = "jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8";
Connection connection = DriverManager.getConnection(url,"root","123456");
Statement statement = connection.createStatement();
String sql = "select * from meet ";
ResultSet execute = statement.executeQuery(sql);
while (execute.next()){
System.out.print(execute.getString(1)+"\t");
System.out.print(execute.getString(2)+"\t");
System.out.print(execute.getString(3)+"\t");
System.out.println(execute.getString(4));
}
connection.close();
statement.close();
execute.close();
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
}
具体步骤
-
创建dbconf.properties文件
## 数据库属性配置信息 ## 连接数据库服务器URL jdbc_url = jdbc:mysql://localhost:3306/(要访问的数据库名)?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC ## 连接数据库服务器驱动类 jdbc_driver = com.mysql.jdbc.Driver ## 访问数据库服务器用户名称 jdbc_UserName = root ## 访问数据库服务器用户密码 jdbc_PassWord = 123456
-
创建Env获取dbconf.properties文件中的属性并设置为静态常量
-
创建数据库管理类,统一管理规范
getConnection()
执行sql语句
Statement statement = connection.createStatement(); String sql = "select * from meet "; ResultSet execute = statement.executeQuery(sql);
查询结果集处理
java,sql.ResultSet 接口是jdbcAPI中唯一用来封装查询结果记录行的组件
遍历结果集中的数据
-
boolean next() 方法 往往做为遍历循环的条件
-
getXxx( int index); getXxx(String colum)
ResultSet execute = statement.executeQuery(sql); while (execute.next()){ System.out.print(execute.getString(1)+"\t"); System.out.print(execute.getString(2)+"\t"); System.out.print(execute.getString(3)+"\t"); System.out.print(execute.getString("name")+"\t"); System.out.println(execute.getString(4)); }
-
封装结果集(使用集合封装)
List<Student> students = new ArrayList(); while (resultSet.next()){ Student stu = new Stundent(); String id = resultSet.getString("id"); stu.setId(id); stu.setName(resultSet.getString("name")); students.add(stu); }
使用map封装
List<Student> students = new ArrayList(); while (resultSet.next()){ Map map = new HashMap(); Student stu = new Stundent(); String id = resultSet.getString("id"); stu.setId(id); stu.setName(resultSet.getString("name")); map.put("学生",stu); students.add(map); }
数据库连接池
-
添加jar包
-
设置 private static ComboPooledDataSource c3p0; //声明数据池对象
-
设置数据源相关属性
private static ComboPooledDataSource c3p0; //声明数据池对象 /** * 创建组合池数据源 */ private static void createComboPooledDataSource() { //判断c3p0数据池是否为空 为空则创建 if (c3p0 == null) { c3p0 = new ComboPooledDataSource(); //为c3p0属性赋值 try { c3p0.setJdbcUrl(Configuration.JDBC_URL); c3p0.setDriverClass(Configuration.JDBC_DRIVER); c3p0.setUser(Configuration.JDBC_USENAME); c3p0.setPassword(Configuration.JDBC_PASSWORD); c3p0.setCheckoutTimeout(5000); } catch (PropertyVetoException e) { e.printStackTrace(); } } } /** * 获得连接 * * @return {@link Connection} */ public static Connection getConnection() { Connection connection = null; createComboPooledDataSource(); //创建数据源 try { connection = c3p0.getConnection(); //由数据源获取一个打开的链接 } catch (SQLException throwables) { throwables.printStackTrace(); } return connection; } /** * 关闭数据库连接的重载方法 */ public static void close(Connection connection) { try { if (connection != null && !connection.isClosed()) { connection.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } public static void close(ResultSet resultSet) { try { if (resultSet != null && !resultSet.isClosed()) { resultSet.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } public static void close(Statement statement) { try { if (statement != null && !statement.isClosed()) { statement.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } public static void main(String[] args) { Connection connection = getConnection(); if (connection != null ){ System.out.println("12345"); } } }
PreparedStatement 是Statement接口的扩展
PreparedStatement 更高效
提供预编译功能,提高数据库访问效率
支持使用占位符设置sql语句参数
此接口对象由Connection调用相关方法创建
设置参数
- setXxx(int index ,Object value)
@Override
public AccountInfo validateAccountInfo(String cardNumber) {
String sql = "SELECT ID,ACCOUNT,ACCOUNT_TYPE,BALANCE,TODAY_OUT_MAX,"
+ "TODAY_TA_MAX,BANKID,FROZEN,LOCATION "
+ "FROM ACCOUNT_INFO WHERE ACCOUNT = ?";
AccountInfo account = null;
Connection connection = null;
ResultSet resultSet = null;
PreparedStatement ps = null;
try {
connection = DataSourcePool.getConnection();
ps = connection.prepareStatement(sql);
ps.setString(1, cardNumber);
resultSet = ps.executeQuery(); //返回结果集
while (resultSet.next()) {
//String date = new SimpleFormatter("yyyy-MM-dd").format(resultSet.getTime("CREATETIME"));
account = new AccountInfo(); //创建新的AccountInfo对象 并给对象赋值
account.setId(resultSet.getString("id"));
account.setAccount(resultSet.getString("ACCOUNT"));
account.setAccountType(resultSet.getInt("ACCOUNT_TYPE"));
account.setBalance(resultSet.getBigDecimal("BALANCE"));
account.setTodayOutMax(resultSet.getBigDecimal("TODAY_OUT_MAX"));
account.setTodayTaMax(resultSet.getBigDecimal("TODAY_TA_MAX"));
account.setBankId(resultSet.getString("BANKID"));
account.setFrozen(resultSet.getInt("FROZEN"));
account.setLocation(resultSet.getString("LOCATION"));
//account.setCreateTime(resultSet.getTime("CREATETIME"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
DataSourcePool.close(ps);
DataSourcePool.close(resultSet);
DataSourcePool.close(connection);
}
return account; //返回创建的对象
}
查询分页
由于数据庞大,全部加载到内存比较耗时,效率低下
-
sql语句实现分页
1.limit用法 limit出现在查询语句最后,可以使用一个参数或两个参数来限制取出的数据, 中第一个参数代表偏移量:offset(可选参数) 第二个参数代表取出的数据条数:rows 单参用法 当指定一个参数时,默认省略了偏移量,及偏移量为0.从第一行开始取数据,一共取rows行 /* 查询前五条数据 */ select * from student limit 5; 双参数用法 当指定两个参数时,需要注意偏移量的取值是从0开始的,此时有两种写法 /* 查询第1-10条数据 */ select * from student limit 0,10; /* 查询第11-20条数据 */ select * from student limit 10,0; 2. 分页公式 总页数计算 在进行计算之前,我们需要先根据数据总量来得出总页数,这需要用到count函数和向上取整函数ceil sql如下: /* 获取总条数 */ select count(*) from student /* 假设每页显示10条,则直接进行除法运算,然后向上取整 */ select ceil(count(*)) as pageTotal from student 核心信息 当前页:pageNumber 每页数量:pageSize 在实际操作中,我们能够得到的信息有当前所在也以及每页的数据量,同时要注意一下是否超出了最大页数,以每页10条为例,则前三页的数据应为: 第一页:第1~10条, limit 0,10 第二页:第11~20条, limit 10,10 第三页:第21~30条,limit 20,10 据此我们可以总结出,limit所需要的两个参数计算公式如下 offset:(pageNumber-1)*pageSize rows:pageSize
分页代码实现
public Map findSalaryPaging(int pageNum, int pageSize){ //计算符合查询条件的总记录数rowCount //计算分页总数pageSum //当前页记录行数rows //返回客户端需要的数据(rowCount,pageSum,rows) } 使用map封装查询信息
JDBC调用存储过程
jdbc调用存储过程实现
优点:执行效率高,提高访问速度
缺点:更换数据库系统时存储过程不兼容
JDBC API 中CallableStatement 接口是唯一处理数据库系统存储过程的通用组件
CallableStatement 接口
方法名称 | 作用说明 |
---|---|
getXxxx(int index) | 以索引的方式获取参数值 |
getXxx(String pName) | 以参数名称的方式获取参数值 |
setXxx(int index,XXX o) | 将数据o按照参数索引位置设置成参数值 |
setXxx(String n,xxx o) | 将数据o按照参数名称设置成参数值 |
registerOutParameter(int i,Types) | 按照参数索引设置返回类型参数的类型 |
registerOutParameter(String n,Types) | 按照参数名称设置返回类型参数的类型 |
execute( ) | 执行调用存储过程并返回boolean值 |
executeUpdate() | 执行调用存储过程并返回int值 |
//定义存储过程名及参数
String proName = “{call pro_hello(?)}”;
//注册一个输出类型
call.regidteroutParameter(1,Types.varchar);
public String callProcedure(String name) {
String procName = "{call pro_hello(?)}"; //定义调用的存储过程及参数
Connection connection = DataSourceForPool.getConnection();
CallableStatement callableStatement = null;
try {
callableStatement = connection.prepareCall(procName);//创建CallableStatement对象
callableStatement.registerOutParameter(1, Types.VARCHAR);//注册一个输出类型
callableStatement.setString(1, name);
callableStatement.execute();//调用存储过程
name = callableStatement.getString(1);
} catch (Exception e) {
e.getMessage();
}
return null;
}
批处理
批处理是指一次连接访问数据中发送一组SQL操作语句,通常对数据库多条数据进行更新操作。
合理使用批处理能够在最少次访问数据库时执行多条SQL操作从而提高数据库的访问速度并提高数据库的应用效率
一般情况下批处理执行类似相近的操作,如批量修改,批量删除,批量插入等
Statement接口批处理方法
void addBatch(String sql) throws SQLException
int [] executeBatch() throws SQLException
void clearCatch() throws SQLException
void addBatch() throws SQLException
JDBC事务处理
Connection事务处理相关方法
void setAutommit(boolean autoCommit) // 传入true则自动提交 false 关闭自动提交
void commit(); //提交事务
void rollback(); //撤销 出现异常 ,异常处理中回滚数据
SavepointsetSavepoint(String name) //保存点
void setTransaction(int level);/设置事务与其他事务的隔离级别
void rollback(Savepoint SavePoint)
Timestamp time = new Times(new Date().getTime()); //获取系统时间
事务的隔离级别
- TRANSACTION_NONE 不支持事务
- TRANSACTION_READ_COMMITTED 禁止脏读和不可重复读,允许虚读(默认)
- TRANSACTION_READ_UNCOMMITTED 允许脏读,不可重复读和虚读
- TRANSACTION_REPEATABLE_READ 禁止脏读和不可重复读;允许虚读
- TRANSACTION_SERIALIZABLE 禁止脏读,不可重复读和虚读
public int withdrawMoney(String accountID, BigDecimal amount, double serviceCharge) {
int res = 0;
/**
* 更新账户余额
*/
String sql0 = " update account_info set BALANCE = (BALANCE -?-?) where account = ?";
/**
* 添加交易记录
*/
String sql2 = " insert into BUSINESS (ID,ACCOUNTID,BUSID,AMOUNT ,"
+ "POUNDAGE,BUSINESS_TIME,DESCRIPTION) "
+ "VALUES(?,?,?,?,?,NOW(),?)";
/**
* 更新ATM余额SQL */
String sql3 = "UPDATE ATM SET TOTAL = TOTAL - ? WHERE ID = ?";
Connection conn = null;
PreparedStatement ps = null;
PreparedStatement ps2 = null;
PreparedStatement ps3 = null;
try {
conn = DataSourcePool.getConnection();
//更新账户余额
conn.setAutoCommit(false);// 关闭自动提交
ps = conn.prepareStatement(sql0);
ps.setBigDecimal(1, amount);
ps.setDouble(2, serviceCharge);
ps.setString(3, accountID);
res += ps.executeUpdate();
//添加交易记录
ps2 = conn.prepareStatement(sql2);
ps2.setString(1, UUID.randomUUID().toString());//生成唯一识别码
ps2.setString(2, Application.atmSys.getAccount().getId());//插入AccountId
ps2.setString(3, "001");//执行的什么操作 (取钱)
ps2.setBigDecimal(4, amount);//交易金额
ps2.setDouble(5, serviceCharge);//交易手续费用
ps2.setString(6, "ATM 取款");
res += ps2.executeUpdate();
//更新ATM余额
ps3 = conn.prepareStatement(sql3);
ps3.setBigDecimal(1, amount);
ps3.setString(2, Application.atmSys.getId());
res += ps3.executeUpdate();
conn.commit();// 提交事务
} catch (Exception e) {
try {
System.out.println("撤销事务");
conn.rollback(); // 撤销事务操作
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
DataSourcePool.close(ps);
DataSourcePool.close(ps2);
DataSourcePool.close(conn);
}
return res;
}