一、连接问题

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

首先写一个配置文件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,普通的须要

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

  1. python sqlite3操作类扩展,包含数据库分页

     一.原因 最近在使用python3和sqlite3编辑一些小程序,由于要使用数据库,就离不开增.删.改.查,sqlite3的操作同java里的jdbc很像,于是就想找现成的操作类,找来找去,发现一个 ...

  2. 实验3、Flask数据库操作-如何使用Flask与数据库

    1. 实验内容 数据库的使用对于可交互的Web应用程序是极其重要的,本节我们主要学习如何与各种主要数据库进行连接和使用,以及ORM的使用 2. 实验要点 掌握Flask对于各种主要数据库的连接方法 掌 ...

  3. java 对excel操作导入excel数据到数据库

    加入jar包jxl.jar ===================services层掉用工具类==================================== // 导入 public Lis ...

  4. 一些常用数据库操作在mysql及sql server中实现方式的差异

    因为本文强调的是不同点,所以先讲述不同点,再讲相同点. 一.不同点 1.创建表时主键id的自增实现方式不一样 mysql数据库的实现方式是auto_increment,示例如下 CREATE TABL ...

  5. 使用JdbcTemplate简化JDBC操作 实现数据库操作

    使用Spring JDBC框架方遍简单的完成JDBC操作,满足性能的需求且灵活性高. Spring JDBC框架由4个部分组成,即core.datasource.object.support. org ...

  6. Django模型-数据库操作

    前言 前边记录的URLconf和Django模板全都是介绍页面展示的东西,也就是表现层的内容.由于Python先天具备简单而强大的数据库查询执行方法,Django 非常适合开发数据库驱动网站. 这篇开 ...

  7. iOS学习笔记(十五)——数据库操作(SQLite)

    SQLite (http://www.sqlite.org/docs.html) 是一个轻量级的关系数据库.SQLite最初的设计目标是用于嵌入式系统,它占用资源非常少,在嵌入式设备中,只需要几百K的 ...

  8. IOS数据库操作SQLite3使用详解(转)

    iPhone中支持通过sqlite3来访问iPhone本地的数据库.具体使用方法如下1:添加开发包libsqlite3.0.dylib首先是设置项目文件,在项目中添加iPhone版的sqlite3的数 ...

  9. PhoneGap 数据库操作

    1,openDatabase phonegap官方文档中已经很清楚的标明,如果使用一个数据库首先要用window对象进行创建: var dbShell = window.openDatabase(na ...

随机推荐

  1. 洛谷——P1916 小书童——蚂蚁大战

    P1916 小书童——蚂蚁大战 题目背景 小A在你的帮助下,开始“刷题”,他在小书童里发现了一款叫“蚂蚁大战”(又称蛋糕保卫战)的游戏.(你懂得) 题目描述 游戏中会出现n只蚂蚁,分别有a1,a2…… ...

  2. Flask实战第47天:首页导航条首先和代码抽离

    新建一个前台页面的父模板front_base.html 导航条是总boostrap v3中文站拷贝过来的,然后根据自己的需求做一些修改 <!DOCTYPE html> <html l ...

  3. grunt-contrib-qunit安装过程中phantomjs安装报错问题解决

    今天自己fork了一个github上别人写的一个关于grunt项目的一个小demo(https://github.com/cowboy/jquery-tiny-pubsub),主要是想学习下grunt ...

  4. ES5 的 Array

    1: Array.isArray判断是否为数组 Array.isArray([1, 2, 3]); // true Array.isArray({foo: 123}); // false // Pol ...

  5. 「NOI2018」屠龙勇士

    「NOI2018」屠龙勇士 题目描述 小\(D\)最近在网上发现了一款小游戏.游戏的规则如下: 游戏的目标是按照编号\(1-n\)顺序杀掉\(n\) 条巨龙,每条巨龙拥有一个初始的生命 值ai .同时 ...

  6. bzoj 2159: Crash 的文明世界

    Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 480  Solved: 234[Submit][Status][Discuss] Descripti ...

  7. BZOJ 4939 [Ynoi2016]掉进兔子洞(莫队+bitset)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4939 [题目大意] 给出一个数列,每个询问给出三个区间,问除去三个区间共有的数字外, ...

  8. 【扫描线】Gym - 101190E - Expect to Wait

    假设初始人数为0, 将每个时刻在等待的人数写下来,就是求个和. 如果纵坐标看成人数,横坐标看成时间,就是求个面积. 因为初始人数不一定为零,所以离线后扫描线即可回答所有询问. #include< ...

  9. 关于热插拔usb hotplug /proc/sys/kernel mdev udev b...

    转:http://www.360doc.com/content/10/0527/18/9922_29835045.shtml 这篇文章说的很好http://blog.chinaunix.net/u1/ ...

  10. java锁对象

    在Java5中,专门提供了锁对象,利用锁可以方便的实现资源的封锁,用来控制对竞争资源并发访问的控制,这些内容主要集中在java.util.concurrent.locks 包下面,里面有三个重要的接口 ...