【java】对数据库操作的那些事(包含数据库中的预处理)

一、连接问题

前面刚介绍了怎么连接数据库,也写了对应的模板。可是它的可维护性很差。那么怎么解决问题呢?

首先写一个配置文件jdbc.properties

<span style="font-size:18px;">## MySQL
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/hncu?

useUnicode=true&characterEncoding=UTF-8
username=root
password=1234

## Oracle
#driver=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@192.168.31.12:1521:orcl
#username=scott
#password=tiger
</span>

然后创建一个生成连接的工厂ConnFactory .java

<span style="font-size:18px;">package cn.hncu.hibernate0;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;

public class ConnFactory {
	private static Connection conn;
	static {
		try {
			//读取配置文件
			Properties p = new Properties();
			p.load(ConnFactory.class.getClassLoader().getResourceAsStream("jdbc.properties"));
			String driver = p.getProperty("driver");
			String url = p.getProperty("url");
			String username = p.getProperty("username");
			String pwd = p.getProperty("password");

			Class.forName(driver);
			conn = DriverManager.getConnection(url,username,pwd);
			System.out.println("已连接到数据库..."+conn);
		} catch (Exception e) {
			throw new RuntimeException("读取配置文件失败", e);
		}
	}
	public static Connection getConn(){
		return conn;
	}
	public static void main(String[] args) {
		getConn();
	}
}
</span>

最后直接通过ConnFactory.getConn()获得。

这要做的优点,当改变所要连接的数据库类型时,仅仅须要改动配置文件里的内容就可以。

二、解说getXXX()方法

<span style="font-size:18px;"><span style="white-space:pre">	</span>@Test
	public void getXXXDemo() throws Exception{
		Statement st = ConnFactory.getConn().createStatement();
		String sql = "select * from book";
		ResultSet rs = st.executeQuery(sql);
		while(rs.next()){
			Integer id = rs.getInt(1);//这里的1表示数据表中的第一列,以下同理
			String name = rs.getString(2);
			//Double price = (Double)rs.getObject(3);//出异常,由于内部是採用BigDecimal来处理
			Double price = rs.getDouble(3);
			Object dateTime = rs.getObject(4);//把日期和时间作为一个总体读取出来
			System.out.println(id+","+name+","+price+","+dateTime);

			String strDateTime = dateTime.toString();
			System.out.println(strDateTime);
			strDateTime = rs.getDate(4)+"--"+rs.getTime(4);//日期和时间能够单独获取
			System.out.println(":::"+strDateTime);
		}
		ConnFactory.getConn().close();
	}</span>

注:对于自己主动增长列。删除之后再插入新记录,序号不会回头,继续往前增长。即中间会出现空号

三、解说Statement中的三个executeXXX()方法

1、executeQuery: 仅仅能运行select语句

2、executeUpdate: 能够运行insert、delete和update语句,但不能运行select

3、execute:增删改查的4种(随意)语句都能运行。该方法若运行非select语句时返回false,运行select语句时返回true,且st对象会缓存该次查询的结果。我

们可通过ResultSet rs = st.getResultSet()来获得结果集

<span style="font-size:18px;"><span style="white-space:pre">	</span>@Test
	public void executeXXXDemo() throws Exception{
		Statement st = ConnFactory.getConn().createStatement();
	    String sql = "select * from book";
		//String sql = "insert into book(name,price,pub) values('软件project',22.35,'2015-12-05 22:12:23')";
		//String sql = "update book set price=38.88 where name='软件project'";
		//String sql = "delete from book where name='软件project'";
	    //st.executeQuery(sql);
		//st.executeUpdate(sql);
		boolean boo = st.execute(sql);

		if(boo){
			ResultSet rs = st.getResultSet();
			while(rs.next()){
				System.out.println(rs.getObject(2));
			}
		}
	}</span>

四、数据库查询时防黑技术(预处理语句)

案例、用户登录(通过用户输入信息来拼接sql语句----非常危急)

<span style="font-size:18px;"><span style="white-space:pre">	</span>@Test//用户登录
	public void login() throws Exception{
		Connection con = ConnFactory.getConn();
		Statement st = con.createStatement();
		Scanner sc = new Scanner(System.in);
		int id = sc.nextInt(); sc.nextLine();
		String name = sc.nextLine();
		String sql = "select count(*) from stud where id="+id+" and sname='"+name+"'";
		System.out.println("sql:"+sql);
		ResultSet rs = st.executeQuery(sql);
		rs.next();
		int a = rs.getInt(1);
		if(a<=0){
			System.out.println("登录不成功");
		}else{
			System.out.println("登录成功");
		}

		con.close();
	}</span>

黑的方法。输入:1002(回车)   1‘ or ‘1‘=‘1

因此:假设须要用 用户输入的信息 来拼接 sql语句,就不能用statement。否则用户能够通过构建where子句中的一个true条件来突破防护对于上面的情

况,应该用PreparedStatement来解决!

<span style="font-size:18px;"><span style="white-space:pre">	</span>@Test//用户登录     黑:1002(回车)   1' or '1'='1
	public void login2() throws Exception{
		Scanner sc = new Scanner(System.in);

		Connection con = ConnFactory.getConn();
		String sql = "select count(*) from stud where id=? and sname=?";//须要用户输入的地方,用占位符('?')来取代。然后在兴许通过设參来给占位符赋值
		PreparedStatement pst = con.prepareStatement(sql);
		//设置參数
		int id = sc.nextInt(); sc.nextLine();
		pst.setInt(1, id); //參数1----代表第1个占位符
		String name = sc.nextLine();
		pst.setString(2, name);//參数2

		ResultSet rs = pst.executeQuery();

		rs.next();
		int a = rs.getInt(1);
		if(a<=0){
			System.out.println("登录不成功");
		}else{
			System.out.println("登录成功");
		}

		con.close();
	}</span>

五、获取自己主动增长列(如id)

<span style="font-size:18px;"><span style="white-space:pre">	</span>@Test //演示获取自己主动增长列如id
	public void saveAuto() throws Exception{
		Connection con = ConnFactory.getConn();
		String sql = "insert into book(name,price,pub) values('JavaEE',100.8,'2013-06-12 08:30:30')";
		Statement st = con.createStatement();

		//st.executeUpdate(sql);
		st.executeUpdate(sql,Statement.RETURN_GENERATED_KEYS);
		ResultSet rs = st.getGeneratedKeys();//里面封装了自己主动生成的全部值
		if(rs.next()){
			int id = rs.getInt(1);//获取第1个自己主动增长列
			System.out.println("自己主动增长的id:"+id);
		}
		System.out.println("-----------------");

		//预处理语句
		sql =  "insert into book(name,price) values(?,?)";
		PreparedStatement pst = con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
		pst.setString(1, "计算机基础");
		pst.setDouble(2, 28);
		pst.executeUpdate();
		ResultSet rs2 = pst.getGeneratedKeys();//里面封装了自己主动生成的全部值
		if(rs2.next()){
			int id = rs2.getInt(1);//获取第1个自己主动增长列
			System.out.println("自己主动增长的id:"+id);
		}
	}</span>

六、演示批处理语句

public void batch() throws Exception{
		Connection con = ConnFactory.getConn();
		String sql = "insert into book(name,price,pub) values('JavaEE',100.8,'2015-06-12 08:30:30')";
		Statement st = con.createStatement();
		for(int i=0;i<10;i++){
			st.addBatch(sql);
		}
		sql = "update book set price=price*1.1 where price>100";
		st.addBatch(sql);
		int[] a = st.executeBatch();
		for(int r:a){
			System.out.println(r);//r为每条sql语句所影响的记录数
		}
	}

预处理

public void preparedBatch() throws Exception{
		Connection con = ConnFactory.getConn();
		String sql = "insert into book(name,price,pub) values(?,?,?)";
		PreparedStatement pst = con.prepareStatement(sql);
		for(int i=0;i<5;i++){
			pst.setString(1, "Java"+i);
			pst.setDouble(2, 55.85+i);
			pst.setString(3, "2016-12-10 07:07:08");
			pst.addBatch(); //pst的方式不能带參数sql
		}
		//pst.executeBatch();
		int[] a = pst.executeBatch();
		for(int r:a){
			System.out.println(r);//r为每条sql语句所影响的记录数
		}
	}

注意:预处理的方式不能带參数sql,普通的须要

时间: 2024-10-17 22:00:31

【java】对数据库操作的那些事(包含数据库中的预处理)的相关文章

MySQL数据库操作2-新建,删除数据库

新建数据库: 代码: create database 数据库名称; 注意: 1.数据库名称最好使用_db后缀,方便识别用户数据库, 2.用户建立的数据库仅用户本人账户和root有权使用. 示例: create database test_db; 删除数据库: 代码: drop database 数据库名; 示例: drop database test_db; 显示所有数据库: 代码: show databases; 注意: 1.databases是复数形式. 数据库存储引擎: 代码: show

【java】对数据库操作的那些事(包括数据库中的预处理)

一.连接问题 前面刚介绍了怎么连接数据库,也写了相应的模板,但是它的可维护性非常差,那么怎么解决这个问题呢? 首先写一个配置文件jdbc.properties <span style="font-size:18px;">## MySQL driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/hncu?useUnicode=true&characterEncoding=UTF-8 username=r

Oracle数据库操作大全(十)——数据库(表)的逻辑备份与恢复

数据库(表)的逻辑备份与恢复--导出 system可导出任何方案,例如: exp system/[email protected] owner(system,scott) file=d:system.dmp;//注:可导出两种方案system方案和Scott方案 exp system/[email protected] owner(scott) file=d:system.dmp;//只可导出Scott方案(这是利用system导出Scott方案,缘由:system权限高于Scott),导出方案

Django模型-数据库操作

前言 前边记录的URLconf和Django模板全都是介绍页面展示的东西,也就是表现层的内容.由于Python先天具备简单而强大的数据库查询执行方法,Django 非常适合开发数据库驱动网站. 这篇开始,进入到了Django模型,也就是数据库操作. 自带 Sqlite3 数据库查询方式 为了简单,使用Python自带的Sqlite3数据库进行实例说明. 先看一个传统的数据库操作示例: 1 from django.shortcuts import render 2 import sqlite3 3

Mysql数据库操作常用命令

转自微信公众号“MySQL数据库”:http://mp.weixin.qq.com/s?__biz=MzIyNjIwMzg4Ng==&mid=2655293044&idx=1&sn=e312934e5115105fdbe5da12af150276&scene=0#wechat_redirect [全了]Mysql数据库操作常用命令 2016-07-21 MySQL数据库 1.MySQL常用命令 create database name; 创建数据库 use database

数据库--操作

一.系统数据库 information_schema :虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数,如用户表信息.列信息.权限信息.字符信息等 mysql:核心数据库,里面包含用户.权限.关键字等信息.不可以删除 performance_schema:mysql 5.5版本后添加的新库,主要收集系统性能参数,记录处理查询请求时发生的各种事件.锁等现象 sys : mysql5.7版本新增加的库,通过这个库可以快速的了解系统的元数据信息,可以方便DBA发现数据库的很多信息,解决性能瓶颈

C#数据库操作通用方法类

平时使用的数据库操作类整理更新后备份,记录下来以供以后使用,并顺便分享给大家一起交流.直接上源码: 整个底层操作方法分为4个类,基础方法类:SqlBase 基础工具类:SqlTool 日志类:DbLog  和MSSQL操作类:MsSqlHelper. 由于平时工作未用到其他类型数据库,因此未整理其他数据库的操作类,以后用到的话会进行更新. 首先是通用的数据库底层操作方法整理: /// <summary> /// 数据库操作基础方法类 /// </summary> public cl

Python练习【6】【数据库操作 | 文件读写】

1. 面向对象,文件操作与数据库操作复习题目: 文件score.dat中保存的是100名学生的姓名和Python课.高数和英语成绩. (1)定义学生类,其中包含姓名.Python课.高数和英语成绩及总分.均分数据成员,成员函数根据需要确定. (2)读入这名学生的成绩,用对象列表进行存储. (3)求出各科和总分的最高分. (4)请按总分的降序(高成绩在前,低成绩在后)排序 (5)在屏幕上显示各科及总分的最高分,排序后的成绩单(包括总分)保存到文件odered_score.dat中. (6) 将文件

十三、EnterpriseFrameWork框架核心类库之数据库操作(多数据库事务处理)

本章介绍框架中封装的数据库操作的一些功能,在实现的过程中费了不少心思,针对不同数据库的操作(SQLServer.Oracle.DB2)这方面还是比较简单的,用工厂模式就能很好解决,反而是在多数据库同时操作方面走了不少弯路:现在从以下几个方面进行说明: 一.不同数据库操作 此处用到了工厂模式来实现不同数据库操作,看下图 AbstractDatabase是一个抽象类,定义了所有对数据库的操作抽象方法,包括执行一个SQL语句.执行存储过程.事务操作等 [Serializable] public abs