JDBC简介:
JDBC全称为:Java DataBase Connectivity(java数据库连接)。
SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC。
组成JDBC的2个包:
链接:https://pan.baidu.com/s/1ePw4wDxcsZu9x-3MZHu8FQ
提取码:0g1z
java.sql
javax.sql
开发JDBC应用需要以上2个包的支持外
还需要导入相应JDBC的数据库实现(即数据库驱动
第一个JDBC程序:
编程从user表中读取数据,并打印在命令行窗口中。
一、搭建实验环境 :
1、在mysql中创建一个库,并创建user表和插入表的数据。
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中取出数据,打印到命令行窗口
六、断开与数据库的连接,并释放相关资源
package cn.itcast.jdbctest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
/**
* JDBC的快速入门
* @author Administrator
*
*/
public class JdbcDemo1 {
@Test
public void run2(){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 现在这么做
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
// 编写SQL语句了
String sql = "select * from t_user";
// 创建能执行SQL语句的Statement对象
stmt = conn.createStatement();
// 执行SQL语句
rs = stmt.executeQuery(sql);
// 循环变量rs
while(rs.next()){
// 拿出来
int id = rs.getInt("id");
String username = rs.getString("username");
String password = rs.getString("password");
System.out.println(id+" "+username+" "+password);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
@Test
public void run1() throws SQLException, ClassNotFoundException{
/**
* 1.完成驱动的注册
* 2.获取链接
* 3.执行SQL语句
* 4.释放资源
*/
// 注册驱动
// DriverManager.registerDriver(new Driver());
// 现在这么做
Class.forName("com.mysql.jdbc.Driver");
// 获取链接
// Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day17", "root", "root");
Connection conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
// 编写SQL语句了
String sql = "select * from t_user";
// 创建能执行SQL语句的Statement对象
Statement stmt = conn.createStatement();
// 执行SQL语句
ResultSet rs = stmt.executeQuery(sql);
// 循环变量rs
while(rs.next()){
// 拿出来
int id = rs.getInt("id");
String username = rs.getString("username");
String password = rs.getString("password");
System.out.println(id+" "+username+" "+password);
}
rs.close();
stmt.close();
conn.close();
}
}
JDBC编程步骤:
装载驱动程序
建立连接
操作数据
释放资源
程序详解—DriverManager:
DriverManager类的是管理一组 JDBC 驱动程序的基本服务。作用有两个,如下:
注册驱动
•static void registerDriver(Driver driver)方法进行注册驱动
•但是这种方式不是很好,原因如下:
•让应用程序依赖具体的驱动包,如果是切换数据库还需要修改源代码才能完成。
•调用该方法导致驱动被注册两次,通过查看驱动的源代码能发现次问题。
•所以在实际开发中不会这么做?具体做法如下:
•Class.forName("com.mysql.jdbc.Driver");
获取链接对象
数据库URL:
URL用于标识数据库的位置,程序员通过URL地址告诉JDBC程序连接哪个数据库,URL的写法为:
l常用数据库URL地址的写法:
•Oracle写法:jdbc:oracle:thin:@localhost:1521:sid
•MySql—jdbc:mysql://localhost:3306/sid
Mysql的url地址的简写形式: jdbc:mysql:///sid
常用属性:useUnicode=true&characterEncoding=UTF-8
程序详解—Connection:
Jdbc程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,
有两个作用:
•创建执行SQL语句的对象:
•createStatement():创建向数据库发送sql的statement对象
•prepareStatement(sql) :创建向数据库发送预编译sql的PreparedSatement对象
•prepareCall(sql):创建执行存储过程的CallableStatement对象。
• 管理事物:
•setAutoCommit(boolean autoCommit):设置事务是否自动提交。
•commit() :在链接上提交事务。 ---与事务相关!!
•rollback() :在此链接上回滚事务。
程序详解—Statement -- 一次操作:
Jdbc程序中的Statement对象用于向数据库发送SQL语句, Statement对象常用方法:
•执行SQL语句
•executeQuery(String sql) :用于向数据发送查询语句。
•executeUpdate(String sql):用于向数据库发送insert、update或delete语句
•execute(String sql):用于向数据库发送任意sql语句
•执行批处理
•addBatch(String sql) :把多条sql语句放到一个批处理中。
•executeBatch():向数据库发送一批sql语句执行。
程序详解—ResultSet:
Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式。ResultSet 对象维护了一个指向表格数据行的游标cursor,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进而调用方法获取该行的数据。
ResultSet既然用于封装执行结果的,所以该对象提供的大部分方法都是用于获取数据的get方法:
•获取任意类型的数据
•getObject(int index)
•getObject(string columnName)
•获取指定类型的数据,例如:
•getString(int index)
•getString(String columnName)
常用数据类型转换表:
遍历查询结果:
程序详解—释放资源:
Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。
特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。
为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。
使用JDBC对数据库进行CRUD:
Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。
CRUD操作-create:
使用executeUpdate(String sql)方法完成数据添加操作,示例操作:
Statement st = conn.createStatement();
String sql = "insert into user(….) values(…..) ";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("插入成功!!!");
}
CRUD操作-updata:
使用executeUpdate(String sql)方法完成数据修改操作,示例操作:
Statement st = conn.createStatement();
String sql = “update user set name=‘’ where name=‘’";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println(“修改成功!!!");
}
CRUD操作-delete:
使用executeUpdate(String sql)方法完成数据删除操作,示例操作:
Statement st = conn.createStatement();
String sql = “delete from user where id=1;
int num = st.executeUpdate(sql);
if(num>0){
System.out.println(“删除成功!!!");
}
CRUD操作-Retrieve/Read:
使用executeQuery(String sql)方法完成数据查询操作,示例操作:
Statement st = conn.createStatement();
String sql = “select * from user where id=1;
ResultSet rs = st.executeQuery(sql);
while(rs.next()){
//根据获取列的数据类型,分别调用rs的相应方法
//映射到java对象中
}
增删改查实例:
package cn.itcast.jdbctest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
import cn.itcast.utils.MyJdbcUtil;
/**
* 完成t_user表的增删改查
* @author Administrator
*
*/
public class JdbcDemo3 {
@Test
public void testSelect(){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 加载驱动,现在不用了,直接获取链接对象
// MyJdbcUtil封装工具类,下文有详细解析,在里面封装了固定的模块,简化代码
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "select * from t_user";
// 创建执行
stmt = conn.createStatement();
// 执行
rs = stmt.executeQuery(sql);
// 循环遍历
while(rs.next()){
System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(rs, stmt, conn);
}
}
/**
* 测试添加的功能
*/
@Test
public void testInsert(){
Connection conn = null;
Statement stmt = null;
try {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取链接
conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
// 编写SQL语句
String sql = "insert into t_user values (null,'小凤','111')";
// 能执行该SQL语句的对象
stmt = conn.createStatement();
// 执行
int index = stmt.executeUpdate(sql);
if(index > 0){
System.out.println("新增数据成功");
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
/**
* 测试修改的功能
*/
@Test
public void testUpdate(){
Connection conn = null;
Statement stmt = null;
try {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取链接
conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
// 编写SQL语句
String sql = "update t_user set username = '如花',password='555' where id = 5 ";
// 能执行该SQL语句的对象
stmt = conn.createStatement();
// 执行
int index = stmt.executeUpdate(sql);
if(index > 0){
System.out.println("修改数据成功");
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
/**
* 测试删除的功能
*/
@Test
public void testDelete(){
Connection conn = null;
Statement stmt = null;
try {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取链接
conn = DriverManager.getConnection("jdbc:mysql:///day17", "root", "root");
// 编写SQL语句
String sql = "delete from t_user where id = 5";
// 能执行该SQL语句的对象
stmt = conn.createStatement();
// 执行
int index = stmt.executeUpdate(sql);
if(index > 0){
System.out.println("删除数据成功");
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
}
JDBC工具类的封装和CURD:
使用JDBC完成数据的CURD操作具有很多重复性的代码,像驱动加载、获取链接、释放资源等,所以可以封装成工具类方便使用。
封装工具类:
package cn.itcast.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* 操作JDBC
* @author Administrator
*/
public class MyJdbcUtil {
public static final String DRIVERCLASS;
public static final String URL;
public static final String USERNAME;
public static final String PASSWORD;
// 想给常量赋值
static{
// 解析db.properties文件
// Properties工具类,加载文件
Properties pro = new Properties();
// 获取输入流
InputStream in = MyJdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
try {
pro.load(in);
} catch (IOException e) {
e.printStackTrace();
}
// 通过Properties获取内容
DRIVERCLASS = pro.getProperty("driverClass");
URL = pro.getProperty("url");
USERNAME = pro.getProperty("username");
PASSWORD = pro.getProperty("password");
}
/**
* 加载驱动
*/
public static void loadDriver(){
try {
Class.forName(DRIVERCLASS);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取链接
* @return
*/
public static Connection getConnection(){
// 加载驱动
loadDriver();
// 获取链接对象
try {
return DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 释放资源
* @param rs
* @param stmt
* @param conn
*/
public static void release(ResultSet rs,Statement stmt,Connection conn){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
/**
* 释放资源的方法
* @param stmt
* @param conn
*/
public static void release(Statement stmt,Connection conn){
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
db.properties配置数据库文件(这个文件是在src的根目录下创建的):
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///day17
username=root
password=root
JavaEE模式-DAO 模式:
SUN公司在早期的JAVAEE体系分成了三层经典结构:WEB层 (Servlet/JSP)– 业务层(JavaBean) – 持久层(JDBC)
早期采用Servlet+JSP+JavaBean+JDBC架构完成开发
现在采用框架来完成开发(ssh框架)Struts2 + Spring + Hibernate
DAO模式就是持久层的一种解决方案,封装对于数据源及其数据的单个操作,需要提供一组接口,供业务层访问,业务调用DAO的代码时候需要传递一个对象。
数据源可能是文件、数据库等任意存储方式
负责管理与数据源的连接
负责数据的存取(CRUD)
DAO模式的类图:
DAO 模式中的对象:
Business Object
•代表数据的使用者
DataAccessObject
•抽象并封装了对底层数据源的操作
DataSource
•数据源
TransferObject
•表示数据的Java Bean
实例(java三层架构模式)—用户登陆:
源码已上传到github:https://github.com/LazyTraveller/standard-login
1.搭建环境
2.导入jar包(MySQL驱动包,JSTL包)
架构:
LoginServlet.java:
package cn.itcast.action;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import cn.itcast.service.UserService;
import cn.itcast.vo.User;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = -5933952794357976456L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 接收数据
* 封装数据
* 处理数据
* 显示结果
*/
// 设置编码
request.setCharacterEncoding("UTF-8");
// 接收数据
Map map = request.getParameterMap();
User user = new User();
try {
// 封装数据
BeanUtils.populate(user, map);
// 调用业务层的代码
UserService us = new UserService();
// 判断是否登陆
User existUser = us.loginUser(user);
// 判断是否为null
if(existUser == null){
// 说明失败
// 向域中存值
request.setAttribute("msg", "用户名或者密码错误");
// 使用转发
request.getRequestDispatcher("/pages/login.jsp").forward(request, response);
}else{
// 把用户的信息保存到session中
request.getSession().setAttribute("existUser", existUser);
// 重定向到页面
response.sendRedirect(request.getContextPath()+"/pages/success.jsp");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
UserDao.java: 这是一个接口
package cn.itcast.dao;
import java.util.List;
import cn.itcast.vo.User;
public interface UserDao {
public User findUser(User user);
public User findUserByPrepared(User user);
// 添加数据
public void insert(User user);
// 修改数据
public void update(User user);
// 删除数据
public void delete(User user);
// 通过主键来查询单个用户
public User findUserById(int id);
// 查询所有用户
public List findUsers();
}
防止SQL注入漏洞:
1.前台校验
2.后台校验(prepareStatement)
UserDaolmple.java: 这是UserDao的实现类
package cn.itcast.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import cn.itcast.utils.MyJdbcUtil;
import cn.itcast.vo.User;
public class UserDaoImple implements UserDao {
/**
* 防止SQL注入
*/
public User findUserByPrepared(User user) {
// 完成登陆的功能(通过用户名和密码查询数据库)
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 先获取链接对象
conn = MyJdbcUtil.getConnection();
// 编写的SQL语句不同
String sql = "select * from t_user where username = ? and password = ? ";
// 预编译(已经把SQL发送给服务器进行预编译,格式就固定了)
stmt = conn.prepareStatement(sql);
// 设置参数的值
stmt.setString(1, user.getUsername()); // bbb ' or ' 1 = 1不认识or关键字
stmt.setString(2, user.getPassword());
// 执行SQL(不带SQL语句的)
rs = stmt.executeQuery();
// 如果有
if(rs.next()){
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
return u;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
/**
* 完成登陆的操作
*/
public User findUser(User user) {
// 完成登陆的功能(通过用户名和密码查询数据库)
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 先获取链接对象
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "select * from t_user where username = '"+user.getUsername()+"' and password= '"+user.getPassword()+"' ";
// 执行SQL
stmt = conn.createStatement();
// 执行SQL语句,如果有会查询出一条记录
rs = stmt.executeQuery(sql);
// 如果有
if(rs.next()){
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
return u;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
/**
* 完成添加的功能
*/
public void insert(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 获取链接
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "insert into t_user values (null,?,?)";
// 预编译SQL
stmt = conn.prepareStatement(sql);
// 设置参数
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
// 执行SQL
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(stmt, conn);
}
}
/**
* 修改用户的数据
*/
public void update(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 获取链接
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "update t_user set username = ? , password = ? where id = ?";
// 预编译SQL
stmt = conn.prepareStatement(sql);
// 设置参数
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
stmt.setInt(3, user.getId());
// 执行SQL
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(stmt, conn);
}
}
/**
* 删除用户的记录
*/
public void delete(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 获取链接
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "delete from t_user where id = ?";
// 预编译SQL
stmt = conn.prepareStatement(sql);
// 设置参数
stmt.setInt(1, user.getId());
// 执行SQL
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(stmt, conn);
}
}
/**
* 通过用户的主键来获取用户的详细信息
*/
public User findUserById(int id) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 获取链接
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "select * from t_user where id = ?";
// 预编译SQL
stmt = conn.prepareStatement(sql);
// 设置参数
stmt.setInt(1, id);
// 执行SQL
rs = stmt.executeQuery();
// 一条记录
if(rs.next()){
User u = new User();
u.setId(id);
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
return u;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
/**
* 获取所有的用户信息
*/
public List findUsers() {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
List list = new ArrayList();
try {
// 获取链接
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "select * from t_user";
// 预编译SQL
stmt = conn.prepareStatement(sql);
// 执行SQL
rs = stmt.executeQuery();
// 一条记录
while(rs.next()){
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
list.add(u);
}
return list;
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
@Test
public void run(){
User u = new User(6,"eee","333");
// insert(u);
// update(u);
// delete(u);
//User u2 = findUserById(2);
//System.out.println(u2);
List list = findUsers();
for (User user : list) {
System.out.println(user);
}
}
}
package cn.itcast.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import cn.itcast.utils.MyJdbcUtil;
import cn.itcast.vo.User;
public class UserDaoImple implements UserDao {
/**
* 防止SQL注入
*/
public User findUserByPrepared(User user) {
// 完成登陆的功能(通过用户名和密码查询数据库)
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 先获取链接对象
conn = MyJdbcUtil.getConnection();
// 编写的SQL语句不同
String sql = "select * from t_user where username = ? and password = ? ";
// 预编译(已经把SQL发送给服务器进行预编译,格式就固定了)
stmt = conn.prepareStatement(sql);
// 设置参数的值
stmt.setString(1, user.getUsername()); // bbb ' or ' 1 = 1不认识or关键字
stmt.setString(2, user.getPassword());
// 执行SQL(不带SQL语句的)
rs = stmt.executeQuery();
// 如果有
if(rs.next()){
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
return u;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
/**
* 完成登陆的操作
*/
public User findUser(User user) {
// 完成登陆的功能(通过用户名和密码查询数据库)
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 先获取链接对象
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "select * from t_user where username = '"+user.getUsername()+"' and password= '"+user.getPassword()+"' ";
// 执行SQL
stmt = conn.createStatement();
// 执行SQL语句,如果有会查询出一条记录
rs = stmt.executeQuery(sql);
// 如果有
if(rs.next()){
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
return u;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
/**
* 完成添加的功能
*/
public void insert(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 获取链接
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "insert into t_user values (null,?,?)";
// 预编译SQL
stmt = conn.prepareStatement(sql);
// 设置参数
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
// 执行SQL
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(stmt, conn);
}
}
/**
* 修改用户的数据
*/
public void update(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 获取链接
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "update t_user set username = ? , password = ? where id = ?";
// 预编译SQL
stmt = conn.prepareStatement(sql);
// 设置参数
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
stmt.setInt(3, user.getId());
// 执行SQL
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(stmt, conn);
}
}
/**
* 删除用户的记录
*/
public void delete(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 获取链接
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "delete from t_user where id = ?";
// 预编译SQL
stmt = conn.prepareStatement(sql);
// 设置参数
stmt.setInt(1, user.getId());
// 执行SQL
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(stmt, conn);
}
}
/**
* 通过用户的主键来获取用户的详细信息
*/
public User findUserById(int id) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 获取链接
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "select * from t_user where id = ?";
// 预编译SQL
stmt = conn.prepareStatement(sql);
// 设置参数
stmt.setInt(1, id);
// 执行SQL
rs = stmt.executeQuery();
// 一条记录
if(rs.next()){
User u = new User();
u.setId(id);
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
return u;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
/**
* 获取所有的用户信息
*/
public List findUsers() {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
List list = new ArrayList();
try {
// 获取链接
conn = MyJdbcUtil.getConnection();
// 编写SQL语句
String sql = "select * from t_user";
// 预编译SQL
stmt = conn.prepareStatement(sql);
// 执行SQL
rs = stmt.executeQuery();
// 一条记录
while(rs.next()){
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
list.add(u);
}
return list;
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
MyJdbcUtil.release(rs, stmt, conn);
}
return null;
}
@Test
public void run(){
User u = new User(6,"eee","333");
// insert(u);
// update(u);
// delete(u);
//User u2 = findUserById(2);
//System.out.println(u2);
List list = findUsers();
for (User user : list) {
System.out.println(user);
}
}
}
UserService.java:
package cn.itcast.service;
import cn.itcast.dao.UserDao;
import cn.itcast.dao.UserDaoImple;
import cn.itcast.vo.User;
/**
* 用户相关的业务类
* @author Administrator
*
*/
public class UserService {
/**
* 用户是否可以登陆
* @param user
* @return
*/
public User loginUser(User user){
UserDao dao = new UserDaoImple();
// 防止SQL注入
return dao.findUserByPrepared(user);
}
}
MyjdbcUtil.java:
package cn.itcast.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* 操作JDBC
* @author Administrator
*/
public class MyJdbcUtil {
public static final String DRIVERCLASS;
public static final String URL;
public static final String USERNAME;
public static final String PASSWORD;
// 想给常量赋值
static{
// 解析db.properties文件
// Properties工具类,加载文件
Properties pro = new Properties();
// 获取输入流
InputStream in = MyJdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
try {
pro.load(in);
} catch (IOException e) {
e.printStackTrace();
}
// 通过Properties获取内容
DRIVERCLASS = pro.getProperty("driverClass");
URL = pro.getProperty("url");
USERNAME = pro.getProperty("username");
PASSWORD = pro.getProperty("password");
}
/**
* 加载驱动
*/
public static void loadDriver(){
try {
Class.forName(DRIVERCLASS);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取链接
* @return
*/
public static Connection getConnection(){
// 加载驱动
loadDriver();
// 获取链接对象
try {
return DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 释放资源
* @param rs
* @param stmt
* @param conn
*/
public static void release(ResultSet rs,Statement stmt,Connection conn){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
/**
* 释放资源的方法
* @param stmt
* @param conn
*/
public static void release(Statement stmt,Connection conn){
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
User.java:
package cn.itcast.vo;
public class User {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User(int id, String username, String password) {
super();
this.id = id;
this.username = username;
this.password = password;
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password="
+ password + "]";
}
}
login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Insert title here
用户登陆
${ msg }
success.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Insert title here
欢迎页面
亲,您还没有登陆,请您登陆
亲,欢迎您:${ existUser.username }
使用JDBC处理大数据:
在实际开发中,程序需要把大文本 Text 或二进制数据 Blob保存到数据库。
Text是mysql叫法,Oracle中叫Clob
基本概念:大数据也称之为LOB(Large Objects),LOB又分为:
•clob和blob
•clob用于存储大文本。Text
•blob用于存储二进制数据,例如图像、声音、二进制文等。
对MySQL而言只有blob,而没有clob,mysql存储大文本采用的是Text,Text和blob分别又分为:
•TINYTEXT(255)、TEXT(64k)、MEDIUMTEXT(16M)和LONGTEXT(4G)
•TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB
使用JDBC处理大文本:
l对于MySQL中的Text类型,可调用如下方法设置:
PreparedStatement.setCharacterStream(index, reader, length);
//注意length长度须设置,并且设置为int型
//当包过大时修改配置:[mysqld] max_allowed_packet=64M
l对MySQL中的Text类型,可调用如下方法获取:
reader = resultSet. getCharacterStream(i);
等价于
reader = resultSet.getClob(i).getCharacterStream();
使用JDBC处理二进制数据:
对于MySQL中的BLOB类型,可调用如下方法设置:
PreparedStatement. setBinaryStream(i, inputStream, length);
对MySQL中的BLOB类型,可调用如下方法获取:
InputStream in = resultSet.getBinaryStream(i);
InputStream in = resultSet.getBlob(i).getBinaryStream();
使用JDBC进行批处理:
业务场景:当需要向数据库发送一批SQL语句执行时,应避免向数据库一条条的发送执行,而应采用JDBC的批处理机制,以提升执行效率。
实现批处理有两种方式,第一种方式:
•Statement.addBatch(sql)
•执行批处理SQL语句
•executeBatch()方法:执行批处理命令
•clearBatch()方法:清除批处理命令
使用JDBC进行批处理:
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtil.getConnection();
String sql1 = "insert into person(name,password,email,birthday)
values('kkk','123','[email protected]','1978-08-08')";
String sql2 = "update user set password='123456' where id=3";
st = conn.createStatement();
st.addBatch(sql1); //把SQL语句加入到批命令中
st.addBatch(sql2); //把SQL语句加入到批命令中
st.executeBatch();
} finally{
JdbcUtil.free(conn, st, rs);
}
采用Statement.addBatch(sql)方式实现批处理:
优点:可以向数据库发送多条不同的SQL语句。
缺点:
SQL语句没有预编译。
当向数据库发送多条语句相同,但仅参数不同的SQL语句时,需重复写上很多条SQL语句。例如:
Insert into user(name,password) values(‘aa’,’111’);
Insert into user(name,password) values(‘bb’,’222’);
Insert into user(name,password) values(‘cc’,’333’);
Insert into user(name,password) values(‘dd’,’444’);
实现批处理的第二种方式:
•PreparedStatement.addBatch()
conn = JdbcUtil.getConnection();
String sql = "insert into person(name,password,email,birthday) values(?,?,?,?)";
st = conn.prepareStatement(sql);
for(int i=0;i<50000;i++){
st.setString(1, "aaa" + i);
st.setString(2, "123" + i);
st.setString(3, "aaa" + i + "@sina.com");
st.setDate(4,new Date(1980, 10, 10));
st.addBatch();
if(i%1000==0){
st.executeBatch();
st.clearBatch();
}
}
st.executeBatch();
采用PreparedStatement.addBatch()实现批处理
•优点:发送的是预编译后的SQL语句,执行效率高。
•缺点:只能应用在SQL语句相同,但参数不同的批处理中。因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据。