javaweb:JDBC连接MYSQL数据库详解,使用JDBC对数据库进行CRUD操作以及DAO模式的介绍

版权声明: https://blog.csdn.net/weixin_42442713/article/details/84450887

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的写法为:

   jdbc:    mysql: //       localhost:3306/test ?     key=value

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<String, String []> 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<User> 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<User> findUsers() {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		List<User> list = new ArrayList<User>();
		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<User> 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<User> findUsers() {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		List<User> list = new ArrayList<User>();
		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<User> 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"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<h3>用户登陆</h3>
<font color="red">${ msg }</font>
<form action="${ pageContext.request.contextPath }/login" method="post">
	用户名:<input type="text" name="username" /><br/>
	密码:<input type="password" name="password" /><br/>
	<input type="submit" value="登陆">
</form>

</body>
</html>

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" %>    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>欢迎页面</h3>
<c:if test="${ empty existUser }">
	<h3>亲,您还没有登陆,请您<a href="${ pageContext.request.contextPath }/pages/login.jsp">登陆</a></h3>
</c:if>

<c:if test="${ not empty existUser }">
	<h3>亲,欢迎您:${ existUser.username }</h3>
</c:if>


</body>
</html>

使用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语句相同,但参数不同的批处理中。因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据。

猜你喜欢

转载自blog.csdn.net/weixin_42442713/article/details/84450887