Dao包结构图:

1.首先连接数据库

 package com.util.db;

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle; import javax.management.loading.PrivateClassLoader; import org.omg.CORBA.PRIVATE_MEMBER; /**
* 连接数据库
* @author Administrator
*
*/
public class DBConn {
public static String URL;
public static String USERNAME;
public static String PASSWORD;
public static String DRIVER;
private static ResourceBundle resourceBundle = ResourceBundle.getBundle("com.util.db.db_config");
private DBConn() {}
/**
*为连接数据库变量赋值
*加载jdbc驱动
*/
static{
URL = resourceBundle.getString("jdbc.url");
USERNAME = resourceBundle.getString("jdbc.username");
PASSWORD = resourceBundle.getString("jdbc.password");
DRIVER = resourceBundle.getString("jdbc.driver");
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 连接数据库,若连接失败则返回空
* @return
*/
public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection(URL, USERNAME,PASSWORD);
System.out.println("连接成功!");
} catch (SQLException e) {
e.printStackTrace();
System.out.println("连接失败");
}
return conn;
}
/**
* 关闭数据库连接
* @param rs
* @param st
* @param conn
*/
public static void close(ResultSet rs,Statement st,Connection conn){
try {
if (rs != null) {rs.close();}
if (st != null) {st.close();}
if (conn !=null) {conn.close();}
} catch (SQLException e) {
e.printStackTrace();
} }
public static void main(String[] args) {
System.out.println(URL);
System.out.println(USERNAME);
System.out.println(PASSWORD);
System.out.println(DRIVER); }
}

连接所需配置文件如下:

jdbc.url = jdbc\:mysql\://localhost\:3306/test?characterEncoding\=utf8
jdbc.username = root
jdbc.password = 000000
jdbc.driver =com.mysql.jdbc.Driver

2.对增删该查基本操作做定义  使用不定参数 来解决增删改的参数不同

 package com.util.db;

 import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; /**
* 为数据库操作提供方法模板
* @author Administrator
*
*/
public class JdbcTemplete {
/**
* 更新操作
* 返回 int 类型的操作行数 用作判断操作成功与否
* 若操作异常 则返回 -1
* @param sql
* @param args
* @return
*/
public int update(String sql,Object...args){
Connection conn = null;
PreparedStatement ps = null;
conn = DBConn.getConnection();
try {
ps = conn.prepareStatement(sql);
if(args!=null){
for(int i = 0; i< args.length; i++){
ps.setObject(i+1, args[i]);
}
} int rs = ps.executeUpdate();
System.out.println("操作成功!");
return rs;
} catch (SQLException e) {
e.printStackTrace();
// try {
// //事务回滚
// conn.rollback();
// } catch (SQLException e1) {e1.printStackTrace();}
System.out.println("更新异常");
return -1;
}finally{
DBConn.close(null, ps, conn);
}
}
/**
* 查询操作 不做结果处理
* 结果处理放在 ResultSetHandler
* 由调用时编写匿名类 采用策略模式 使用户采用不同策略 处理不同对象
* @param sql
* @param handler
* @param args
* @return
*/
public Object query(String sql, ResultSetHandler handler, Object...args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBConn.getConnection();
ps = conn.prepareStatement(sql);
if (args != null) {
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1, args[i]);
}
}
rs = ps.executeQuery();
return handler.doHandler(rs);
} catch (SQLException e) {
e.printStackTrace();
return null;
}finally{
DBConn.close(rs, ps, conn);
}
}
}

3.对操作查询结果作出接口声明  使用策略模式  对于不同的javaBean有不同的处理

package com.util.db;

import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 操作连接数据库的结果集
* 声明接口可以对具体的实体做不同处理
* @author Administrator
*
*/
public interface ResultSetHandler {
public Object doHandler(ResultSet rs) throws SQLException;
}

4.定义javaBean

 package com.domain;

 public class Person {
private int id;
private String name;
private int age;
private String description;
public Person() {
super();
}
public Person(String name, int age, String description) {
super();
this.name = name;
this.age = age;
this.description = description;
}
public Person(int id, String name, int age, String description) {
super();
this.id = id;
this.name = name;
this.age = age;
this.description = description;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", age=" + age
+ ", description=" + description + "]";
} }

5. 定义Dao  对具体操作  声明接口

 package com.dao;

 import java.sql.SQLException;
import java.util.List; import com.domain.Person; /**
* 用户功能接口
* @author Administrator
*
*/
public interface PersonDao {
public void add(Person person)throws SQLException;
public void update(Person person)throws SQLException;
public void delete (int id)throws SQLException;
public Person findById(int id)throws SQLException;
public List findAll()throws SQLException; }

6.对用户的操作进行实现

 package com.dao.impl;

 import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List; import javax.management.j2ee.statistics.JDBCConnectionPoolStats; import com.dao.PersonDao;
import com.domain.Person;
import com.util.db.JdbcTemplete;
import com.util.db.ResultSetHandler; public class PersonDaoImpl implements PersonDao {
private JdbcTemplete jdbcTemplete;
public PersonDaoImpl(){
jdbcTemplete = new JdbcTemplete();
}
/**
* 添加
*/
@Override
public void add(Person person) throws SQLException {
String sql = "insert into person(name,age,description)value(?,?,?)";
jdbcTemplete.update(sql, person.getName(),person.getAge(),person.getDescription()); }
/**
* 更新操作
*/
@Override
public void update(Person person) throws SQLException {
String sql ="update person set name=?,age=?,description=? where id=?";
jdbcTemplete.update(sql, person.getName(),person.getAge(),person.getDescription(),person.getId());
} @Override
public void delete(int id) throws SQLException {
String sql = "delete from person where id = ?";
jdbcTemplete.update(sql,id);
} @Override
public Person findById(final int id) throws SQLException {
String sql = "select name,age,description from person where id =?";
return (Person) jdbcTemplete.query(sql, new ResultSetHandler() {
@Override
public Object doHandler(ResultSet rs) throws SQLException {
Person person = null;
if (rs.next()) {
person = new Person();
person.setId(rs.getInt(id));
person.setName(rs.getString(1));
person.setAge(rs.getInt(2));
person.setDescription(rs.getString(3));
}
return person;
}
},id ); } @Override
public List findAll() throws SQLException {
String sql = "select id,name,age,description from person";
return (List) jdbcTemplete.query(sql,new ResultSetHandler() {
@Override
public Object doHandler(ResultSet rs) throws SQLException {
List<Person> personList = new ArrayList<>();
Person person =null;
while (rs.next()) {
person = new Person();
person.setId(rs.getInt(1));
person.setName(rs.getString(2));
person.setAge(rs.getInt(3));
person.setDescription(rs.getString(4));
personList.add(person);
}
return personList;
}
}); } }

7.编写测试类

 package com.test;

 import java.sql.SQLException;
import java.util.List; import com.dao.PersonDao;
import com.dao.impl.PersonDaoImpl;
import com.domain.Person; public class Test {
/**
*
* @param args
*/
public static void main(String[] args) {
PersonDao personDao = new PersonDaoImpl(); try { // personDao.add(new Person("CCC", 13, "CCC")); personDao.delete(3);
//
// personDao.update(new Person(3, "DDD", 10, "DDD"));
//
//
// Person p4 = personDao.findById(2);
// System.out.println(p4.toString());
//
//
// List<Person> personList = personDao.findAll();
// for (Person p : personList) {
// System.out.println(p.toString());
// } } catch (SQLException e) {
e.printStackTrace();
}
}
}
1.Statement、PreparedStatement和CallableStatement都是接口(interface)。  
2.Statement继承自Wrapper、PreparedStatement继承自Statement、CallableStatement继承自PreparedStatement。 
3.  
 a.Statement:  
    普通的不带参的查询SQL;支持批量更新,批量删除;  
 b.PreparedStatement:  
    可变参数的SQL,支持占位符,每个占位符可占一个位,
     编译一次,执行多次,效率高;  
    安全性好,有效防止Sql注入等问题;  
    支持批量更新,批量删除;  
 c.CallableStatement:  
    继承自PreparedStatement,支持带参数的SQL操作;  
    支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持; 
PreparedStatement是预编译的,使用PreparedStatement有几个好处  
1. 在执行可变参数的一条SQL时,PreparedStatement比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。 
2. 安全性好,有效防止Sql注入等问题。  
3.  对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch;  
4.  代码的可读性和可维护性。

如何防止注入攻击:

如果你是做Java web应用开发的,那么必须熟悉那声名狼藉的SQL注入式攻击。去年Sony就遭受了SQL注入攻击,被盗用了一些Sony play station(PS机)用户的数据。在SQL注入攻击里,恶意用户通过SQL元数据绑定输入,比如:某个网站的登录验证SQL查询代码为:

strSQL = "SELECT * FROM users WHERE name = '" + userName + "' and pw = '"+ passWord +"';"

恶意填入:

userName = "1' OR '1'='1";
passWord = "1' OR '1'='1"

那么最终SQL语句变成了:

strSQL = "SELECT * FROM users WHERE name = '1' OR '1'='1' and pw = '1' OR '1'='1';"

因为WHERE条件恒为真,这就相当于执行:

strSQL = "SELECT * FROM users;"

因此可以达到无账号密码亦可登录网站。如果恶意用户要是更坏一点,再在后面加一句  :

drop  table users;

SQL语句变成了:

strSQL = "SELECT * FROM users;drop  table users;

这样一来,虽然没有登录,但是数据表都被删除了。

  然而使用PreparedStatement的参数化的查询可以阻止大部分的SQL注入。在使用参数化查询的情况下,数据库系统(eg:MySQL)不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,参数只是用作参数,而不会作为指令拼成SQL语句,因此就算参数中含有破坏性的指令,也不会被数据库所运行。
补充:避免SQL注入的第二种方式:
在组合SQL字符串的时候,先对所传入的参数做字符取代(将单引号字符取代为连续2个单引号字符,因为连续2个单引号字符在SQL数据库中会视为字符中的一个单引号字符,譬如:

strSQL = "SELECT * FROM users WHERE name = '" + userName + "';"

传入字符串:

userName  = " 1' OR 1=1 "

把userName做字符替换后变成:

userName = " 1'' OR 1=1"

最后生成的SQL查询语句为:

strSQL = "SELECT * FROM users WHERE name = '1'' OR 1=1'

这样数据库就会去系统查找name为“     1′ OR 1=1     ”的记录,而避免了SQL注入。

CallableStatement使用:

  

public class Conn {
public static String URL;
public static String USERNAME;
public static String PASSWORD;
public static String DRIVER;
private static ResourceBundle resourceBundle = ResourceBundle.getBundle("com.util.db.db_config");
private void Conn() {}
static{
URL = resourceBundle.getString("jdbc.url");
USERNAME = resourceBundle.getString("jdbc.username");
PASSWORD = resourceBundle.getString("jdbc.password");
DRIVER = resourceBundle.getString("jdbc.driver");
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 连接数据库,若连接失败则返回空
* @return
*/
public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection(URL, USERNAME,PASSWORD);
System.out.println("连接成功!");
} catch (SQLException e) {
e.printStackTrace();
System.out.println("连接失败");
}
return conn;
}
/**
* 关闭数据库连接
* @param rs
* @param st
* @param conn
*/
public static void close(ResultSet rs,CallableStatement cstmt,Connection conn){
try {
if (rs != null) {rs.close();}
if (cstmt != null) {cstmt.close();}
if (conn !=null) {conn.close();}
} catch (SQLException e) {
e.printStackTrace();
}
} /**
* 1、执行不带参数但有返回值的存储过程
*/
static public int getUserCount() {
Connection conn = Conn.getConnection();
CallableStatement cstmt = null;
int rowsCount = 0;
try {
String sql = "{call getUserCount(?)}";
//创建CallableStatement 对象
cstmt = conn.prepareCall(sql);
//注册输出参数
cstmt.registerOutParameter(1,Types.INTEGER);
//执行存储过程
cstmt.execute(); rowsCount = cstmt.getInt(1);
} catch (SQLException e) {
System.out.println("执行失败!");
e.printStackTrace();
}finally {
Conn.close(null,cstmt, conn);
return rowsCount;
}
}
/**
* 2、执行带参数带返回值的存储过程
*/
static public int getUserCountCondit(String username) {
Connection conn = Conn.getConnection();
CallableStatement cstmt = null;
int rowsCount = 0;
try {
String sql = "{call proc_getUserCountCondit(?,?)}";
//创建CallableStatement 对象
cstmt = conn.prepareCall(sql);
//输入参数赋值
cstmt.setString(1,username);
//注册输出参数
cstmt.registerOutParameter(1,Types.INTEGER);
//执行存储过程
cstmt.execute(); rowsCount = cstmt.getInt(1);
} catch (SQLException e) {
System.out.println("执行失败!");
e.printStackTrace();
}finally {
Conn.close(null,cstmt, conn);
return rowsCount;
}
}
/**
* 3、执行返回值为游标的存储过程
*/
static public List<User> getUserListByProc(){
Connection conn = Conn.getConnection();
CallableStatement cstmt = null;
ResultSet rs = null;
List<User> userList = new ArrayList();
try {
String sql = "{? = call FUNC_GETUSERNAME(?)}";
//创建CallableStatement 对象
cstmt = conn.prepareCall(sql);
//注册输出参数
cstmt.registerOutParameter(1,Types.REF_CURSOR);
//执行存储过程
cstmt.execute();
rs = cstmt.getResultSet(); while (rs.next()) {
String username = rs.getString("username");
String password = rs.getString("password");
userList.add(new User(username, password));
}
} catch (SQLException e) {
System.out.println("执行失败!");
e.printStackTrace();
}finally {
Conn.close(rs,cstmt, conn);
return userList;
}
}
public static void main(String[] args) { } static class User{
String username = null;
String password = null; public User(String username, String password) {
super();
this.username = username;
this.password = password;
}
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;
} }
}

简易 DBUtil 封装的更多相关文章

  1. MongoDB 系列(一) C# 简易入门封装

    之前写过一篇关于MongoDB的封装 发现太过繁琐 于是打算从新写一篇简易版 1:关于MongoDB的安装请自行百度,进行权限认证的时候有一个小坑,3.0之后授权认证方式默认的SCRAM-SHA-1模 ...

  2. C#基于websocket-sharp实现简易httpserver(封装)

    一.背景 其实就是很简单的,公司会桌面开发的人员紧缺啊,项目又赶,而我们公司的前端人员人多还厉害(ps:吐槽下,后端的人真的少啊,会桌面开发的更少啊),所以萌生出了使用html+js来构建本地应用程序 ...

  3. 对xlslib库与libxls库的简易封装

    一.简介 xlslib库是用来创建excel文件.libxls是用来读取excel文件的,在使用C++或者QT语言来设计对excel文件的读取.都需要事先下载这两个库编译成功后再进行程序设计的.之所以 ...

  4. AFNetworking2.0简易GET,POST请求封装以及使用

    AFNetworking2.0简易GET,POST请求封装以及使用 AFNetworking不用我赘述其强大性,本人仅仅做了非常简易的封装,解决了有时候请求出错的问题,提供源码给大家. 封装源码库下载 ...

  5. node.js + mssql 简易封装操作

    时间吧,总是这么凑巧,在我学习[node.js]还没几天,我的 Microsoft SQL Server Management Studio 18 就歇菜了,至于怎么歇菜的吧....它可能的意思就是想 ...

  6. 用Go实现的简易TCP通信框架

    接触到GO之后,GO的网络支持非常令人喜欢.GO实现了在语法层面上可以保持同步语义,但是却又没有牺牲太多性能,底层一样使用了IO路径复用,比如在LINUX下用了EPOLL,在WINDOWS下用了IOC ...

  7. JavaWeb -学生信息管理实践(JDBC+web+三层架构+DBUtil构造思路)

    前言: 1 该程序使用动态web项目 2 该程序使用SQL server需导入对应包( 具体可看前篇----JDBC的使用) 3 三层架构思想: ①表示层 前台:jsp/html等 作为前台与用户交互 ...

  8. Linux网络编程中tcp_server和tcp_client函数的封装

    本文的主要目的是将server套接字和client套接字的获取,做一个简易的封装,使用C语言完成.   tcp_server   服务器端fd的获取主要分为以下几步: 1.创建socket,这一步仅仅 ...

  9. Linux组件封装(一)中互斥锁MutexLock的封装

    本文对Linux中的pthread_mutex_t做一个简易的封装. 互斥锁主要用于互斥,互斥是一种竞争关系,主要是某一个系统资源或一段代码,一次做多被一个线程访问. 条件变量主要用于同步,用于协调线 ...

随机推荐

  1. 笔试算法题(30):从已排序数组中确定数字出现的次数 & 最大公共子串和最大公共序列(LCS)

    出题:在已经排序的数组中,找出给定数字出现的次数: 分析: 解法1:由于数组已经排序,所以可以考虑使用二分查找确定给定数字A的第一个出现的位置m和最后一个出现的位置n,最后m-n+1就是A出现的次数: ...

  2. 2 SQL 查询基础

    2 查询基础 2-1 SELECT语句基础 通过SELECT语句查询并选取必要数据的过程称为匹配查询或查询(query). 子句是SQL语句的组成要素,是以SELECT或者FROM等作为起始的短语. ...

  3. Python之微信-微信机器人

    一 简介 二 登录微信 三 微信好友男女比例 四 微信好友地域分布 五 微信聊天机器人 一 简介 wxpy基于itchat,使用了 Web 微信的通讯协议,,通过大量接口优化提升了模块的易用性,并进行 ...

  4. Python之机器学习-sklearn生成随机数据

    sklearn-生成随机数据 import numpy as np import pandas as pd import matplotlib.pyplot as plt from matplotli ...

  5. Python之购物车

    Python之购物车 msg_list = [ ['iphone',8888], ['coffe',38], ['book',90], ['Tesla',100000], ['RR',10000000 ...

  6. windows事件查看器

    如果一个软件发生异常,软件本身没有提示异常信息, 需要从事件查看器中查看产生的错误事件 运行输入eventvwr或者win + X

  7. python 博客开发之散乱笔记

    博客开发之旅: # 回滚,数据存储失败时,还原修改操作 from django.db import transaction with transaction.atomic(): do... ... # ...

  8. [luoguP1058] 立体图(超级大模拟(¬︿̫̿¬☆))

    传送门 看到题后整个人成了mengbier 但是仔细分析一下就很简单了,先确定好输出的图的长和宽. 然后从输入的矩形的左上角的最下面的开始填充,顺序是从下到上,从左到右,从后往前. 填充的时候直接覆盖 ...

  9. 2018/2/27 Activiti教程之创建流程篇(与Springboot整合版)一

    因为电脑还在托运中,现在手上这台垃圾电脑实在是没法玩微服务,所以趁着这两天玩玩Activiti吧. 说实话,在学习Activiti中走了N多弯路,最大的原因就是网上没有一个完整(好)的教程,甚至连官方 ...

  10. 【Intellij 】Intellij IDEA 添加jar包的三种方式

    一.直接复制:(不推荐) 方法:直接将硬盘上的jar包复制粘贴到项目的lib目录下即可. 注意: 1.对于导入的eclipse项目,该方式添加的jar包没有任何反应,用make编译项目会报错 2.对于 ...