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. seq2seq(1)- EncoderDecoder架构

    零 seq2seq是从序列到序列的学习过程,最重要的是输入序列和输出序列是可变长的,这种方式就非常灵活了,典型的机器翻译就是这样一个过程. 一 最基本的seq2seq网络架构如下所示: 可以看到,en ...

  2. https://blog.csdn.net/blmoistawinde/article/details/84329103

    背景    很多场景需要考虑数据分布的相似度/距离:比如确定一个正态分布是否能够很好的描述一个群体的身高(正态分布生成的样本分布应当与实际的抽样分布接近),或者一个分类算法是否能够很好地区分样本的特征 ...

  3. jquery腾讯换肤的一些技术实现

    //检查cookie if($.cookie("skinID")){ $("#cssSkin").attr("href","/st ...

  4. MFC定时器的使用

    巧妙地使用定时器能达到意想不到的效果,写界面的时候能实现渐变,也能帮助多线程控制等我们知道,在VC的MFC中,已经为我们封装好了很多全面和强大的函数集,所以在MFC编程时,巧妙地调用MFC函数库可以为 ...

  5. Go:方法

    一.基本介绍 在某些情况下,我们需要定义方法.比如 Person 结构体,除了有一些字段外(姓名.年龄...),还可以有一些行为动作(吃.唱歌...),这就需要用方法才能实现. Go中的方法是作用在指 ...

  6. c++基础_01字串

    #include <iostream> using namespace std; int main(){ for(int a=0;a<=1;a++){ for(int b=0;b&l ...

  7. YOLOv3配置(win10+opencv3.40+cuda9.1+cudnn7.1+vs2015)

    最近心血来潮想学一下YOLOv3,于是就去网上看了YOLOv3在win10下的配置教程.在配置过程中塌坑无数,花了很多时间和精力,所以我想就此写一篇博客来介绍在在win10+vs2015的环境下如何配 ...

  8. Python数组列表(List)

    Python数组列表 数组是一种有序的集合,可以随时添加和删除其中的元素. 一.数组定义: 数组是最常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现. 数组的数据项不需要具有相同的类 ...

  9. HTML基础知识 table中 th,td,tr

    https://www.2cto.com/kf/201711/701872.html table是一个布局神器,之前看过很多代码,都是用table布局的.但是,我在学习的过程中,发现table有很迷的 ...

  10. [luoguP1082] 同余方程(扩展欧几里得)

    传送门 ax≡1(mod b) 这个式子就是 a * x % b == 1 % b 相当于 a * x - b * y == 1 只有当 gcd(a,b) == 1 时才有解,也就是说 ax + by ...