JDBC:Java DataBase Connectivity(java数据库连接)
SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC。
jdbc是一套标准,它是由一些接口与类组成的。
涉及到的类与接口: java.sql 类:DriverManger 接口 Connection Statement ResultSet PreparedStatement CallableStatement(它是用于调用存储过程) javax.sql 接口 DataSource
驱动:
两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。
不同的数据库不同的驱动,有了JDBC这套标准,我们只需要学JDBC就可以。
无JDBC和有JDBC:
一、搭建实验环境 :
1、创建一数据库库,并创建表和插入表的数据。
2、新建一个Java工程,并导入数据驱动。
二、编写程序,在程序中加载数据库驱动
DriverManager. registerDriver(Driver driver)
三、建立连接(Connection)
Connection conn = DriverManager.getConnection(url,user,pass);
四、创建用于向数据库发送SQL的Statement对象,并发送sql
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);
五、从代表结果集的ResultSet中取出数据,打印到命令行窗口
六、断开与数据库的连接,并释放相关资源
JDBC中的类:
static void registerDriver(Driver driver) 注册一个JDBC驱动程序
注意:DriverManager中可以同时注册多个JDBC驱动 例如:同时注册 mysql、oralce、db2 驱动 ,通过对JDBC URL分析,决定采用哪个驱动
static Connection getConnection(String url, String user, String password) 根据jdbc url 和 用户名、密码获得一个数据库连接
实际开发中,不推荐使用DriverManager.registerDriver 会导致驱动注册两次、会使得程序依赖 具体数据库API
推荐使用 :Class.forName("com.mysql.jdbc.Driver"); 加载Driver类时完成驱动注册,使得程序不依赖MySQL的API
***** 不要引入 与数据库相关 具体 API
jdbc:mysql://localhost:3306/day13
这里 jdbc: 是JDBC连接协议
这里 mysql:// 是mysql数据库连接协议,JDBC子协议
localhost:3306 主机和端口
应用一:获得SQL的操作对象
Statement conn.createStatement() 该对象可以将SQL发送给数据库进行执行
PreparedStatement conn.prepareStatement(sql) 对SQL语句进行预编译,防止SQL注入
CallableStatement conn.prepareCall(sql); 该对象可以调用数据库中存储过程 (以后Oracle学习)
应用二:对数据库事务进行管理(明天)
conn.setAutoCommit(boolean); 设置事务是否自动提交
conn.commit(); 提交数据库事务
conn.rollback(); 回滚数据库事务
发送单条SQL
executeUpdate 用于向数据库发送 insert update delete 语句,返回int 类型参数,代表影响记录行数
executeQuery 用于向数据库发送 select 语句,返回ResultSet 结果集对象
execute 用于数据库发送任何SQL语句(包括 DDL DML DCL) 返回boolean ,SQL执行结果是ResultSet 返回true,否则 false
发送多条SQL
addBatch(sql) 将SQL加入批处理队列
executeBatch() 执行队列中所有SQL语句 ,一次性向数据库发送多条SQL
while(rs.next()){
// 根据数据库内部 列类型,选择相应 getXXX方法
int ---- getInt
varchart ---- getString
date ----- getDate
}
在java.sql 定义Date、Time 、TimeStamp 对应数据库中 date time timestamp 类型 --------------- java.sql.Date/Time/TimeStamp 都是 java.util.Date 子类
java.sql.Date 只有日期没有时间
java.sql.Time 只有时间没有日期
java.sql.TimeStamp 既有日期也有时间
getXXX 有两种写法 第一种 getString(index) 结果集中列索引 第二种 getString(列名)
思考:如果SQL语句可能会返回一行数据,也可能查不到任何记录时,代码应该怎么写? ----- 用于登陆
if(rs.next()){
// 查到了数据
}else{
// 没有查到数据
}
Connection 接口的 createStatement() 返回Statement对象,操作SQL后 产生ResultSet 默认执行next 向前滚动,不支持在滚动中对数据进行修改 (只读不执行滚动)
Connection 接口还提供 createStatement(int resultSetType, int resultSetConcurrency) 在创建Statement对象 设置结果集类型,并发策略
结果集类型
ResultSet.TYPE_FORWARD_ONLY 只能向前,只能调用next 不能向回滚动
ResultSet.TYPE_SCROLL_INSENSITIVE 支持结果集向回滚动,不能查看修改结果
ResultSet.TYPE_SCROLL_SENSITIVE 支持结果集向回滚动,查看修改结果
结果集并发策略
ResultSet.CONCUR_READ_ONLY 只读
ResultSet.CONCUR_UPDATABLE 支持修改
常见三种组合
ResultSet.TYPE_FORWARD_ONLY 和 ResultSet.CONCUR_READ_ONLY (默认) 只读不支持向回滚动
ResultSet.TYPE_SCROLL_INSENSITIVE 和 ResultSet.CONCUR_READ_ONLY 只读,支持向回滚动
ResultSet.TYPE_SCROLL_SENSITIVE 和 ResultSet.CONCUR_UPDATABLE 支持向回滚动,支持对数据修改
首先专门写一个类链接数据库
顺序:先用 init() 初始化链接,拿到链接之后调用 con.prepareStatement(sql) 把 sql 语句传进去,返回对象给pste,然后调用 pste.executeQuery(); 查询,返回结果集给 rs ,然后遍历结果集输出内容。最后关闭。
package com.hanqi.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcConnectionUtil {
private static final String USERNAME = "test";//用户名
private static final String PASSWORD = "test";//数据库密码
private static final String URL = "jdbc:oracle:thin:@localhost:1521:xe";
private static final String DRIVERCLASSNAME = "oracle.jdbc.OracleDriver";//加载链接数据库的驱动包,需要将驱动包粘贴到WEB-INF下lib下
public static Connection getConnection() {
Connection conn = null;
try {
Class.forName(DRIVERCLASSNAME);//加载驱动
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
public static void destroy(Connection conn, Statement sm, ResultSet rs) {
if (conn != null) {
try {
conn.close();
conn = null;//没有指向,垃圾回收
} catch (SQLException e) {
e.printStackTrace();
}
}
if (sm != null) {
try {
sm.close();
sm = null;
} catch (SQLException e) {
e.printStackTrace();
}
}
if (rs != null) {
try {
rs.close();
rs = null;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
package com.hanqi.dal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.hanqi.model.AppUser;
import com.hanqi.model.Dept;
import com.hanqi.model.Emp;
import com.hanqi.util.JdbcConnectionUtil;
public class MethodDal {
private Connection con;
private PreparedStatement ps;
private ResultSet rs;
public List<AppUser> selectAppUser() {
String sql = "select a.id,a.username hh,a.password,a.realname,a.createtime from appuser a where a.id in (76,73)";
init();
List<AppUser> list = new ArrayList<AppUser>();
try {
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) {
/* AppUser au = new AppUser(
rs.getInt("id"),
rs.getString("hh"),
rs.getString("password"),
rs.getString("realname"),
rs.getDate("createtime"));*/
AppUser au = new AppUser();
au.setId(rs.getInt(1));
au.setUsername(rs.getString(2));
au.setPassword(rs.getString(3));
au.setRealname(rs.getString(4));
au.setCreatetime(rs.getDate(5));
list.add(au);
}
} catch (SQLException e) {
e.printStackTrace();
}
close();
return list;
}
public List<Emp> selectEmpWithDept() {
String sql = "SELECT e.ename,d.dname FROM p_emp e, p_dept d "
+ "WHERE e.deptno=d.deptno AND d.deptno=30";
init();
List<Emp> list = new ArrayList<Emp>();
// List<Dept> list = new ArrayList<Dept>();
try {
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()) {
Emp emp = new Emp();
Dept dept = new Dept();
emp.setEname(rs.getString("ename"));
dept.setDname(rs.getString("dname"));
emp.setDept(dept);
list.add(emp);
}
} catch (SQLException e) {
e.printStackTrace();
}
close();
return list;
}
public void init() {
con = JdbcConnectionUtil.getConnection();
}
public void close() {
JdbcConnectionUtil.destroy(con, ps, rs);
}
}
实际使用中不应该设置为静态变量,因为静态变量只有一个值。如同以下,可以作为测试理解
package com.hanqi.test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.hanqi.util.JdbcConnectionUtil;
public class Test {
private static Connection con;//获取链接
private static PreparedStatement pste;// 用来执行SQL语句
private static ResultSet rs;//
public static void main(String[] args) {
init();//调用链接的方法
String sql = "select * from appuser";
try {
pste = con.prepareStatement(sql);//获取执行SQL的对象
rs = pste.executeQuery();
while(rs.next()) {
System.out.println(rs.getInt("id"));
System.out.println(rs.getString("username"));
System.out.println(rs.getString("password"));
System.out.println(rs.getString("realname"));
System.out.println(rs.getDate("createtime"));
System.out.println("================================");
}
} catch (SQLException e) {
e.printStackTrace();
}
close();
}
public static void init() {
con = JdbcConnectionUtil.getConnection();
}
public static void close() {
JdbcConnectionUtil.destroy(con,pste,rs);
}
}
添加内容:
?占位符:后面的语句会根据顺序找到相应的第几个占位符
// 添加指定的参数
public int insertData(AppUser user) {
init();
int i = -1;
String sql = "insert into appuser " + "values(testsq.nextval,?,?,?,?)";
long l = new Date().getTime();
try {
ps = con.prepareStatement(sql);
ps.setString(1, user.getUsername());
ps.setString(2, user.getPassword());
ps.setString(3, user.getRealname());
ps.setDate(4, new java.sql.Date(l));
i = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
close();
return i;
}
// 批量添加数据
public int[] insertBatchData() {
init();
int[] arr = null;
try {
String sql = "insert into appuser values(testsq.nextval,?,?,?,sysdate)";
ps = con.prepareStatement(sql);
for (int i = 0; i < 5; i++) {
ps.setString(1, "user" + i);
ps.setString(2, "1234" + i);
ps.setString(3, "名称" + i);
ps.addBatch();//批量
}
arr = ps.executeBatch();
} catch (SQLException e) {
e.printStackTrace();
}
close();
return arr;
}
删除、修改、查询
package com.hanqi.dal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.hanqi.model.AppUser;
import com.hanqi.model.Dept;
import com.hanqi.model.Emp;
import com.hanqi.util.JdbcConnectionUtil;
public class MethodDal {
private Connection con;
private PreparedStatement ps;
private ResultSet rs;
// 删除一条记录
public int deleteData(int id) {
init();
int i = -1;
String sql = "delete appuser a where a.id=?";
try {
ps = con.prepareStatement(sql);
ps.setInt(1, id);
i = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
close();
return i;
}
// 更新表中的数据
public int updateData(int id, String realname) {
init();
int i = -1;
String sql = "update appuser a set a.realname=? where a.id=?";
try {
ps = con.prepareStatement(sql);
ps.setString(1, realname);
ps.setInt(2, id);
i = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
close();
return i;
}
public List<AppUser> selectAppUser() {
String sql = "select a.id,a.username hh,a.password,a.realname,a.createtime from appuser a where a.id in (76,73)";
init();
List<AppUser> list = new ArrayList<AppUser>();
try {
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) {
/* AppUser au = new AppUser(
rs.getInt("id"),
rs.getString("hh"),
rs.getString("password"),
rs.getString("realname"),
rs.getDate("createtime"));*/
AppUser au = new AppUser();
au.setId(rs.getInt(1));
au.setUsername(rs.getString(2));
au.setPassword(rs.getString(3));
au.setRealname(rs.getString(4));
au.setCreatetime(rs.getDate(5));
list.add(au);
}
} catch (SQLException e) {
e.printStackTrace();
}
close();
return list;
}
public List<Emp> selectEmpWithDept() {
String sql = "SELECT e.ename,d.dname FROM p_emp e, p_dept d "
+ "WHERE e.deptno=d.deptno AND d.deptno=30";
init();
List<Emp> list = new ArrayList<Emp>();
// List<Dept> list = new ArrayList<Dept>();
try {
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()) {
Emp emp = new Emp();
Dept dept = new Dept();
emp.setEname(rs.getString("ename"));
dept.setDname(rs.getString("dname"));
emp.setDept(dept);
list.add(emp);
}
} catch (SQLException e) {
e.printStackTrace();
}
close();
return list;
}
public void init() {
con = JdbcConnectionUtil.getConnection();
}
public void close() {
JdbcConnectionUtil.destroy(con, ps, rs);
}
}
用户注册与登录的验证:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="com.util.User,java.util.*,com.test.*" errorPage="error.jsp" %>
<%
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
%>
<%
String sub_type = request.getParameter("sub_type");
String password = request.getParameter("password");
String password1 = request.getParameter("password1");
MethodDal m=new MethodDal();
if("reg".equals(sub_type)) {
String username = request.getParameter("username");
if (!password.equals(password1)) {
out.print("两次输入的密码不一致 !");
} else {
String selectname=m.selectName(username);
if (!selectname.equals("no")) {
out.print("用户名已经存在 !");
} else {
User user = new User();
user.setUsername(username);
user.setPassword(password);
m.insertData(user);
out.print("注册成功 !");
}
}
out.print("<br>");
out.print("<a href='denglu.jsp'>跳转登陆</a>");
}
if("log".equals(sub_type)) {
String username = request.getParameter("username");
String selectname=m.selectName(username);
String spwd=m.selectPwd(password);
if(username.equalsIgnoreCase(selectname)&&password.equalsIgnoreCase(spwd)) {
session.setAttribute("currentUser", 1);
response.sendRedirect("Maintest.jsp");
} else {
out.print("用户名或密码不正确 !");
}
out.print("<br>");
out.print("<a href='denglu.jsp'>跳转登陆</a>");
}
%>
package com.test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import com.util.JdbcConnectionUtil;
import com.util.User;
public class MethodDal {
private Connection con;
private PreparedStatement pste;
private ResultSet rs;
//向表中添加数据
public int insertData(){
init();
int i=-1;
String sql="insert into puser values('c','c')";
try {
pste=con.prepareStatement(sql);
i=pste.executeUpdate();//针对于增删改数据吗,返回受影响的行数
} catch (SQLException e) {
e.printStackTrace();
}
return i;
}
//向表中添加数据
public int insertData(User user){
init();
int i=-1;
String sql="insert into puser values(?,?)";
try {
pste=con.prepareStatement(sql);
pste.setString(1,user.getUsername());
pste.setString(2, user.getPassword());
i=pste.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return i;
}
//删除记录
public int deleteDate(int id){
return 0;
}
//查现有姓名
public String selectName(String name){
init();
String sql="select * from puser p where p.pname=?";
try {
pste=con.prepareStatement(sql);
pste.setString(1,name);
rs = pste.executeQuery();
while(rs.next()) {
String pname=rs.getString("pname");
if(pname!=null){
return pname;
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return "no";
}
//根据姓名查密码
public String selectPwd(String name){
init();
String sql="select * from puser p where p.pname=?";
try {
pste=con.prepareStatement(sql);
pste.setString(1,name);
rs = pste.executeQuery();
while(rs.next()) {
String pwd=rs.getString("ppassword");
return pwd;
}
} catch (SQLException e) {
e.printStackTrace();
}
return "wu";
}
public void init(){
con=JdbcConnectionUtil.getConnection();
}
}