常用api
数据库连接配置
URL:连接数据库系统资源描述符
DriverClass:数据库系统驱动类名称
UserName:登录数据库系统用户名称
Password:登录数据库系统用户密码
数据库连接信息通常以普通文本属性文件进行配置dbconf.properties
创建属性文件
## 数据库属性配置信息
jdbc_url = jdbc:oracle:thin:@127.0.0.1:1521:orcl
jdbc_driver = oracle.jdbc.driver.OracleDriver
jdbc_system = system
jdbc_password = system
读取这个文件
package com.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public final class Env extends Properties {
public static final String JDBC_URL;
public static final String JDBC_DRIVER;
public static final String JDBC_USER;
public static final String JDBC_PASSWORD;
private static final String CONF_FILE="com/conf/dbconf.properties";
private static Env env;
static{
if(env == null){
env = new Env();//加载文件流
}
/*获取指向文件的输入流*/
InputStream in = env.getClass().getClassLoader().getResourceAsStream(CONF_FILE);
try {
env.load(in);
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
JDBC_URL = env.getProperty("jdbc_url");
JDBC_DRIVER = env.getProperty("jdbc_driver");
JDBC_USER = env.getProperty("jdbc_system");
JDBC_PASSWORD = env.getProperty("jdbc_password");
}
private Env(){
}
public static void main(String[] args) {
System.out.println(Env.JDBC_DRIVER);
System.out.println(Env.JDBC_PASSWORD);
System.out.println(Env.JDBC_URL);
System.out.println(Env.JDBC_USER);
/*oracle.jdbc.driver.OracleDriver
system
jdbc:oracle:thin:@127.0.0.1:1521:orcl
system
*/
}
}
建立数据源管理组件
package com.util;
import java.sql.*;
/*数据源管理组件,提供最基本的通用数据库链接*/
public final class DateSourceManager {
/*提供目标数据源的连接通用方法*/
public static Connection getConnection(){
Connection conn = null;
try {
//加载数据库驱动
Class.forName(Env.JDBC_DRIVER);
conn = DriverManager.getConnection(Env.JDBC_URL,Env.JDBC_USER,Env.JDBC_PASSWORD);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
/*关闭数据库连接的通用方法*/
public static void close(Connection conn){
try {
if(conn != null && !conn.isClosed()){ //如果不是空且灭有断开
conn.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public static void close(Statement state){
try {
if(state != null && !state.isClosed()){
state.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
public static void close(ResultSet set){
try {
if(set != null && !set.isClosed()){
set.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
编写DAO数据处理组件
定义更新,删除,添加、查询功能
先给出相关的java类
package com.pojo;
/*映射部门信息*/
public class Department {
private int id;//部门id
private String name;//部门名称
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
类的相关文件存入pojo文件夹中
添加数据
package com.dao;
import com.pojo.Department;
import com.util.DateSourceManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/*数据访问组件,实现增删改查操作*/
public class DeptDao {
public int addDepartment(Department dep){
int res = 0;
String sql = "insert into dep values(?,?) ";
Connection conn = DateSourceManager.getConnection();//获取数据库链接
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);//获取prepareStatement对象
/*设置替换sql语句中参数占位符 ? */
ps.setString(1,dep.getName());
ps.setString(2,String.valueOf(dep.getId()));
res = ps.executeUpdate();//数据更新
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally{
DateSourceManager.close(ps);
DateSourceManager.close(conn);
}
return res;
}
}
测试:
package com.test;
import com.dao.DeptDao;
import com.pojo.Department;
public class testDepDao {
public static void main(String[] args) {
Department dep1 = new Department();
dep1.setId(7);
dep1.setName("摸鱼部");
DeptDao dDao = new DeptDao();
int res = dDao.addDepartment(dep1);
System.out.println("影响数据库表中的行数是:" + res);//影响数据库表中的行数是:1
}
}
在运行测试时,出现了java.sql.SQLRecoverableException: IO 错误: Undefined Error
根据这条链接解决
结果:
修改数据,
/*修改选定 部门对象*/
public int modifyDepartment(Department dep){
int res = 0;
String sql = "update dep set dep_name=? where id = ?";
Connection conn = DateSourceManager.getConnection();
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
ps.setString(1,dep.getName());
ps.setString(2,String.valueOf(dep.getId()));
res = ps.executeUpdate();
}catch (Exception e){
e.printStackTrace();
}finally {
DateSourceManager.close(ps);
DateSourceManager.close(conn);
}
return res;
}
/*测试修改数据*/
Department dep2 = new Department();
dep2.setName("生活部");
dep2.setId(2);
int res2 = dDao.modifyDepartment(dep2);
System.out.println(res2);
结果:
删除数据
/*根据部门id删除部门*/
public int deleteDepartmentById(String id){
int res = 0;
String sql = "delete from dep where id = '" + id + "'";
Connection conn = DateSourceManager.getConnection();
PreparedStatement ps = null;
try{
ps = conn.prepareStatement(sql);
//执行删除操作
res = ps.executeUpdate();
}catch (SQLException e){
e.printStackTrace();
}finally {
DateSourceManager.close(ps);
DateSourceManager.close(conn);
}
return res;
}
}
new DeptDao().deleteDepartmentById("7");
结果(把id为7的删除了)
查找数据
Java.sql.ResultSet接口是jdbcAPI中唯一用来封装查询结果记录行的组件,ResultSet接口唯一创建方式是通过执行SQL查询返回创建此对象
/*查询获取部门所有列表*/
public List<Department> queryDepartmentList(){
List<Department> depList = new ArrayList<Department>();
String sql = "select id,dep_name from dep";//可以根据数据库跟着写
Connection conn = DateSourceManager.getConnection();
PreparedStatement ps = null;
ResultSet set = null;
try {
ps = conn.prepareStatement(sql);
set = ps.executeQuery();//注意这里是exexuteQuery提交查询
/*处理结果集,封装成对象*/
while (set.next()) {
Department dep = new Department();
String idTemp = set.getString(1);//获取部门id
dep.setId(Integer.parseInt(idTemp));
dep.setName(set.getString(2));//获取部门名称
depList.add(dep);
}
}catch (SQLException e){
e.printStackTrace();
}finally {
DateSourceManager.close(set);
DateSourceManager.close(ps);
DateSourceManager.close(conn);
}
return depList;
}
package com.test;
import com.dao.DeptDao;
import com.pojo.Department;
import java.util.ArrayList;
public class baseQureyTest {
public static void main(String[] args) {
//测试查询结果
ArrayList<Department> depList = (ArrayList)new DeptDao().queryDepartmentList();
for(Department dep:depList){
System.out.println("id:" + dep.getId() + ",name" + dep.getName());
}
}
}
结果:
连接池
这里使用了c3p0的,连接池有很多,在网上下载jar包后使用
package com.util;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public final class DataSourceForPool {
private static ComboPooledDataSource c3p0;
public static void createComboPooledDateSource(){
if(c3p0 == null){
c3p0 = new ComboPooledDataSource();
}
/*数据源相关属性*/
try {
c3p0.setDriverClass(Env.JDBC_DRIVER);
c3p0.setUser(Env.JDBC_USER);
c3p0.setPassword(Env.JDBC_PASSWORD);
c3p0.setJdbcUrl(Env.JDBC_URL);
c3p0.setCheckoutTimeout(3000);/*设置超时时间*/
c3p0.setDataSourceName("c3p0DateSource");/*设置名称*/
c3p0.setMaxPoolSize(30);/*最大池数量*/
}catch(PropertyVetoException e){
e.printStackTrace();
}
}
public static Connection getConnection(){
Connection conn = null;
createComboPooledDateSource();//创建数据源
try {
conn = c3p0.getConnection();//由数据源获取一个打开的链接
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return conn;
}
/*以下方法跟DateSourceManager一致*/
/*关闭数据库连接的通用方法*/
public static void close(Connection conn){
try {
if(conn != null && !conn.isClosed()){
//如果不是空且灭有断开
conn.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public static void close(Statement state){
try {
if(state != null && !state.isClosed()){
state.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
public static void close(ResultSet set){
try {
if(set != null && !set.isClosed()){
set.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
上述代码的功能跟之前的DateSourceManager的功能大体一致,但使用c3p0可以更方便的设置
实现分组聚合统计查询(使用连接池的方式)
上一份代码写了连接池的相关类,这里开始使用
先贴出在数据库中的emp类和dep类
其中,emp.dep_id 和dep.id 是外键约束
我们要实现以下查询
/*分组查询员工信息聚合*/
public List<Map<String,Object>> queryListMap(){
List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
String sql = "select dep.dep_name 部门名称,\n" +
"e.dep_id 部门代号,\n" +
"count(e.dep_id) 部门人数,\n" +
"sum(e.salary) 部门所发薪水总数,\n" +
"max(e.salary) 部门中最高工资 \n" +
"from emp e \n" +
"left join dep on dep.id = e.dep_id\n" +
"group by e.dep_id,dep.dep_name"; //注意这个group by,因为left join,所以要加上dep_name
Connection conn = DataSourceForPool.getConnection();
PreparedStatement ps = null;
ResultSet set = null;
try {
ps = conn.prepareStatement(sql);
set = ps.executeQuery(); //返回查询ResultSet结果集对象
while(set.next()){
Map<String,Object> map = new HashMap<String, Object>();
map.put("部门代号",set.getString("部门代号"));
map.put("部门名称",set.getString("部门名称"));
map.put("部门人数",set.getString("部门人数"));
map.put("部门所发薪水总数",set.getString("部门所发薪水总数"));
map.put("部门中最高工资",set.getInt("部门中最高工资"));
list.add(map);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
DataSourceForPool.close(set);
DataSourceForPool.close(ps);
DataSourceForPool.close(conn);
}
return list;
}
测试
List<Map<String, Object>> list = new DeptDao().queryListMap();
for(Map map:list){
/*查询结果懒得输了*/
System.out.println(map.get("部门代号"));
}
结果:
分页查询
/*分页查询显示员工薪水记录*/
public Map<String,Object> querySalaryByPaging(int pageNum,int pageSize){
Map<String,Object> map = new HashMap<String, Object>();
Connection conn = DateSourceForPool.getConnection();
PreparedStatement ps2 = null; //执行查询统计条目数
PreparedStatement ps3 = null; //执行查询结果集
ResultSet set2 = null; // 封装统计条目的结果集
ResultSet set3 = null; // 封装统计查询结果集
int rowCount = 0;
int pageSum = 0;
String rowcountSql = "select count(sid) rowcounts from emp";
String pagingSql = "select e3.sid,e3.name,e3.address,e3.salary from\n" +
"(select rownum rt,e2.* from emp e2 where rownum <= ?) e3\n" +
"where e3.rt >= ?";
try {
//统计符合查询条件的总记录行数rowcounts
ps2 = conn.prepareStatement(rowcountSql);
set2 = ps2.executeQuery();
while (set2.next()){
rowCount = set2.getInt(1);
}
map.put("rowCount",rowCount);
//统计总共分成多少页(总记录行数 / pageSize)
pageSum = this.countPageSum(rowCount,pageSize);
map.put("pageSum",pageSum);
// 统计符合条件每页结果集
ps3 = conn.prepareStatement(pagingSql);
ps3.setInt(1,pageSize * pageNum);//设置第一个问好
ps3.setInt(2,pageSize * pageNum - (pageNum - 1));//设置第二个?
set3 = ps3.executeQuery();
List<Map<String,Object>> rows = new ArrayList<Map<String, Object>>();
while(set3.next()){
Map<String,Object> rowMap = new HashMap<String,Object>();
rowMap.put("sid",set3.getString("sid"));
rowMap.put("name",set3.getString("name"));
rowMap.put("address",set3.getString("address"));
rowMap.put("salary",set3.getDouble("salary"));
rows.add(rowMap);
}
map.put("rows",rows);
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
DateSourceForPool.close(set2);
DateSourceForPool.close(set3);
DateSourceForPool.close(ps2);
DateSourceForPool.close(ps3);
DateSourceForPool.close(conn);
}
return map;
}
/*计算分成多少页的函数*/
private int countPageSum(int rowCount,int pageSize){
return rowCount % pageSize ==0 ? rowCount / pageSize : rowCount / pageSize + 1;
}
package com.test;
import com.dao.DeptDao;
import java.util.List;
import java.util.Map;
public class testPaging {
public static void main(String[] args) {
//输入页码1 每页显示行数为5
Map<String,Object> map = new DeptDao().querySalaryByPaging(1,6);
Object rowCount = map.get("rowCount").toString();//符合条件记录总数
System.out.println("符合条件记录总数:" + rowCount);
List<Map<String,Object>> rows = (List<Map<String, Object>>) map.get("rows");
for(Map<String,Object> row:rows){
System.out.println(row.get("name"));
}
}
}
结果:
JDBC处理存储过程
JDBCAPI 中CallableStatement接口是唯一处理数据库系统存储过程的通用组件
例一
sql中的proc定义如下:
create or replace procedure pro_hello(username in out varchar2) as
hello string(4) := '你好';
begin
username := hello || ' ' || username;
end pro_hello;
jdbc调用带输入输出的存储过程
/*调用带输入输出的存储过程*/
public String callProcedure(String name){
String procName = "{call pro_hello(?)}";// 定义调用的过程及参数
Connection conn = DateSourceForPool.getConnection();
CallableStatement call = null;
try {
call = conn.prepareCall(procName);//创建callablestatement对象
call.registerOutParameter(1, Types.VARCHAR);// 注册一个输出类型
call.setString(1,name);//设置输入的参数值
call.execute(); //调用存储过程
name = call.getString(1);//获取输出类型参数值
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
DateSourceForPool.close(call);
DateSourceForPool.close(conn);
}
return name;
}
System.out.println(new DeptDao().callProcedure("张飞"));//hello 张飞
例二
SQL中一个返回查询表的函数
create or replace procedure pro_dep_info(dates out sys_refcursor)
as
begin
open dates for select * from dep;
end pro_dep_info;
java代码
/*存储过程返回表*/
public List<Department> callProcedure2(){
List<Department> list = new ArrayList<>();
String procSql = "{call pro_dep_info(?)}";
Connection conn = DateSourceForPool.getConnection();
CallableStatement call = null;
ResultSet rSet = null;
try {
call = conn.prepareCall(procSql);
call.registerOutParameter(1, OracleTypes.CURSOR);//注册oracle游标类型,可以封装查询结果
call.execute();
rSet = (ResultSet) call.getObject(1);//返回输出类型
while (rSet.next()){
Department dep = new Department();
dep.setId(Integer.parseInt(rSet.getString("id")));
dep.setName(rSet.getString("dep_name"));
list.add(dep);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
DateSourceForPool.close(rSet);
DateSourceForPool.close(call);
DateSourceForPool.close(conn);
}
return list;
}
测试
List<Department> list = new DeptDao().callProcedure2();
for(Department d:list){
System.out.println(d.getName());
}
结果(返回部门名称):
数据库批量操作
批处理(Batch proces)是指一次连接访问数据中发送一组SQL操作语句,通常对数据库多条数据行进行更新操作。
一般执行批量修改、批量删除、批量插入
在数据库中新建了一个person表,暂时为空,在java中建立相关类如下:
建立PersonDao类进行数据库批量插入处理
package com.dao;
import com.pojo.Person;
import com.util.DateSourceForPool;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
public class PersonDao {
/*实现批处理插入数据*/
public void testButchInsert(List<Person> list){
String sql = "insert into person values(?,?,?,?)";
Connection conn = DateSourceForPool.getConnection();
try {
PreparedStatement ps = conn.prepareStatement(sql);
for(Person p:list){
ps.setString(1,p.getId());
ps.setString(2,p.getName());
ps.setString(3,p.getSex());
ps.setInt(4,p.getAge());
/*将以上设置添加到批处理命令中*/
ps.addBatch();
}
/*提交批处理命令,提交数据库执行sql操作*/
int[] res = ps.executeBatch();//返回int类型的数组
for(int i = 0;i < res.length;i++){
System.out.println("第" + (i+1) + "条语句影响数据库的行数是" + res[i]);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
DateSourceForPool.close(conn);
}
}
}
在数据库中的结果:
jdbc事务处理
参考这个链接
总结
三周多的时间接触数据库和jdbc,总感觉还有好多东西没有知晓,但为了就业,也只能匆匆离开。时间不多了,还需要加快进度。