Java JDBC的基础知识(四)
之前学习了如何创建一个数据库工具类,如下:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; public class DBUtil {
// 私有化构造方法
private DBUtil() {
} private static String url = "";
private static String user = "";
private static String password = "";
private static String className = "";
static {
try {
Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} // 得到連接
public static Connection getConn() {
@SuppressWarnings("unused")
Connection conn = null;
try {
conn = DriverManager.getConnection(url, user, password);
} catch (SQLException e) { e.printStackTrace();
} return null;
} // 关闭连接
public static void close(ResultSet rs, Statement stm, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (stm != null) {
try {
stm.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
} }
}
}
现在主要是学习如何使用这个工具类。简单了解CURD的实现过程。
在百度百科中关于CURD是这样解释的:
CURD是一个数据库技术中的缩写词,一般的项目开发的各种参数的基本功能都是CURD。作用是用于处理数据的基本原子操作。
它代表创建(Create)、更新(Update)、读取(Retrieve)和删除(Delete)操作。CURD 定义了用于处理数据的基本原子操作。.之所以将CURD 提升到一个技术难题的高度是因为完成一个涉及在多个数据库系统中进行CRUD操作的汇总相关的活动,其性能可能会随数据关系的变化而有非常大的差异。CURD 操作通常是使用关系型数据库系统中的结构化查询语句(Structured Query Language,SQL)完成的。随着 Web 变得更加具有面向数据特性,因此需要从基于 SQL 的 CURD 操作转移到基于语义 Web 的 CURD 操作。
呃,一言以蔽之——增删改查。
一、增加操作
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement; //增加操作
public class Test3 {
static int add(StuInfo stu) {
int result = 0; Connection conn = null;
Statement stm = null; try {
conn = DBUtil.getConn();
stm = conn.createStatement();
String sql = "insert into stuInfo(name,age,shoolId) values('"
+ stu.getName() + "'," + stu.getAge() + ","
+ stu.getSchoolId() + ")";// 字符串类型不要忘记加单引号
result = stm.executeUpdate(sql);// 返回值代表数据库中受影响的行数
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DBUtil.close(null, stm, conn);
}
return result;
} public static void main(String[] args) {
StuInfo stu = new StuInfo();
stu.setName("阿三");
stu.setAge("25");
stu.setSchoolId(3); int result = add(stu);
if (result > 0) { // 这里写result=1,编译通不过
System.out.println("操作成功");
} else {
System.out.println("操作失败");
} }
}
二、删除操作
//刪除操作
static int delStuById(int id){
int result=0;
Connection conn=null;
Statement stm=null; try{
conn=DBUtil.getConn();
stm=conn.createStatement();
String sql="delete from stuInfo where id=4"+id;
result=stm.executeUpdate(sql);
}catch(Exception e){
e.printStackTrace();
}finally{
DBUtil.close(null,stm,conn)
}
return result;
}
三、更新操作
//更新操作
static int updateStudent(StuInfo stu) {
int result = 0;
Connection conn = null;
Statement stm = null;
try {
conn = DBUtil.getConn();
stm = conn.createStatement();
String sql = "update stuInfo set name='" + stu.getName() + "',age="
+ stu.getAge() + ",schoolId=" + stu.getSchoolId()
+ " where id=" + stu.getId() + " ";
result=stm.executeUpdate(sql);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
DBUtil.close(null, stm, conn);
}
return result;
}
四、查找操作
// 查询操作
static StuInfo getStuById(int id){
StuInfo stu=null; Connection conn=null;
ResultSet rs=null;
Statement stm=null; try{
conn=DBUtil.getConn();
stm=conn.createStatement();
String sql="select * from stuInfo where id="+id;
rs=stm.executeQuery(sql);
if(rs.next()){
stu=new StuInfo();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
stu.setSchoolId(rs.getInt("schoolId"));
} }catch(Exception ex){
ex.printStackTrace();
}finally{
DBUtil.close(rs,stm,conn);
} return stu;
}
查找出列表
//查询出列表
public static List<StuInfo> getAllStudent(){
List<StuInfo> stuList=new ArrayList<StuInfo>(); Connection conn=null;
ResultSet rs=null;
Statement stm=null; try{
conn=DBUtil.getConn();
stm=conn.createStatement();
String sql="select * from stuInfo " ;
rs=stm.executeQuery(sql);
while(rs.next()){
StuInfo stu=new StuInfo();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
stu.setSchoolId(rs.getInt("schoolId")); stuList.add(stu);
} }catch(Exception ex){
ex.printStackTrace();
}finally{
DBUtil.close(rs,stm,conn);
} return stuList;
} public static void main(String[] args) {
List<StuInfo> stuList=getAllStudent();
for(int i=0;i<stuList.size();i++){
System.out.println(stuList.get(i));
} }
五、SQL 注入攻击
因为在给sql语句传参的时候,使用了字符串拼接的方式,所以导致了这种漏洞。
比如,注入串 : 1' or '1'='1,使得密码安全性缺失。
解决:
String sql="select * from admininfo where userName ='"+userName+"' and password='"+password+"' ";
六、PreparedStatement
在SQL中包含特殊字符或SQL的关键字(如: ' or 1 or ')时Statement将出现不可预料的结果(出现异常或查询的结果不正确),可用PreparedStatement来解决。
PreparedStatement 是 从 Statement 扩展来的
优点:
1) 解决sql注入攻击
2) Statement 会使数据库频繁编译sql,可能造成数据缓冲区溢出
3) 数据库和驱动,可以对 PreparedStatement 进行优化
代码示例:
// 防注入的登录
public static AdminInfo getLoginAdmin(String userName,String password){
AdminInfo admin=null;
Connection conn=null;
ResultSet rs=null;
PreparedStatement stm=null; //第一处 try{
conn=DBUtil.getConn();
String sql="select * from adminInfo where userName=? and password=?" ; //第二处:改成占位符表示
stm=conn.preparedStatement(sql);//第三处:注意,扩号里要传参,这条代码,要放在下面的两条之前
stm.setString(1,userName);//地四处:传参
stm.setString(2,password); rs=stm.executeQuery();//第五处:如果用preparedStatement,这里不要传参 if(rs.next()){
admin=new AdminInfo();
admin.setId(rs.getInt("id"));
admin.setUserName(rs.getString("userName"));
admin.setPassword(rs.getString("password"));
admin.setAddress(rs.getString("address"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
DBUtil.close(rs,stm,sonn);
}
return admin;
}
六、几种常见的特殊类型
1).DATA,TIME,TIMESTAMP-> date,time,datetime
存:stm.setDate(i,d); stm.setTime(i,t); stm.setTimestamp(i, ts);
取:rs.getDate("birthday"); rs.getTime(i); rs.getTimestamp(i);
2).CLOB -> text
存:ps.setCharacterStream(index, reader, length);
ps.setString(i, s);
取:reader = rs. getCharacterStream(i);
reader = rs.getClob(i).getCharacterStream();
string = rs.getString(i);
3).BLOB -> blob
存:ps.setBinaryStream(i, inputStream, length);
取:rs.getBinaryStream(i);
rs.getBlob(i).getBinaryStream
演示1:日期类型
//日期類型
//java.sql.Date是java.util.Date的子类
public static int add(AdminInfo admin){
int result = 0;
Connection conn = null;
PreparedStatement stm = null;
try {
conn = DBUtil.getConn();
String sql="insert into adminInfo (userName,password,address, createDate,birthday) values (?,?,?,?,?) ";
stm = conn.prepareStatement(sql);
stm.setString(1, admin.getUserName());
stm.setString(2, admin.getPassword());
stm.setString(3, admin.getAddress());
//stm.setDate(4,admin.getCreateDate());//要的是子类,父类传不进去
stm.setDate(4, new java.sql.Date(admin.getCreateDate().getTime())); //可以用字符串类型处理data
stm.setString(5, admin.getBirthday());
result=stm.executeUpdate();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
DBUtil.close(null, stm, conn);
}
return result;
}
}
public static void main(String[] args) {
AdminInfo admin=new AdminInfo();
admin.setUserName("阿三");
admin.setPassword("123");
admin.setAddress("杭州文一西路");
admin.setCreateDate(new Date());
admin.setBirthday("1999-03-05 12:20:40");
int result=add(admin);
if(result>0){
System.out.println("成功");
}else{
System.out.println("失败");
}
}
演示2:大文本处理
//将c盘的文件 index.html 读入数据库
static int addContent(){
int result=0;
Connection conn=null;
PreparedStatement stm=null;
try{
conn=DBUtil.getConn();
String sql="insert into t_testclob (content) values (?)";
stm=conn.prepareStatement(sql); Reader br=new BufferedReader(new FileReader("c:\\index.html"));
stm.setCharacterStream(1, br); result=stm.executeUpdate(); br.close(); }catch(Exception ex){
ex.printStackTrace();
}finally{
DBUtil.close(null, stm, conn);
} return result;
}
演示3:读文件并保存到指定位置
//把text类型的数据,读出来,存到e盘
static void getContent(){
Connection conn=null;
PreparedStatement stm=null;
ResultSet rs=null;
try{
conn=DBUtil.getConn();
String sql="select * from t_testclob";
stm=conn.prepareStatement(sql);
rs=stm.executeQuery(); while(rs.next()){
BufferedReader r=new BufferedReader(rs.getCharacterStream("content")); BufferedWriter bw=new BufferedWriter(new FileWriter("e:\\testxxx.txt"));
String str=null;
while((str=r.readLine())!=null){
bw.write(str);
bw.newLine();
bw.flush();
} bw.close();
r.close();
} }catch(Exception ex){
ex.printStackTrace();
}finally{
DBUtil.close(null, stm, conn);
}
}
演示4:从数据库中读取图片
public static void getPhoto(){
ResultSet rs=null;
Connection conn=null;
PreparedStatement stm=null;
try{
conn=DBUtil.getConn();
String sql="select * from t_testblob";
stm=conn.prepareStatement(sql);
rs=stm.executeQuery(); int i=0;
while(rs.next()){
// rs.getString("content");
InputStream in=rs.getBinaryStream("photo");
OutputStream out=new BufferedOutputStream(new FileOutputStream("e:\\test"+i++ +".bmp" ));
byte [] buff=new byte[1024];
int len=0;
while((len=in.read(buff))!=-1){
out.write(buff,0,len);
}
out.close();
in.close();
}
}catch(Exception ex){
ex.printStackTrace();
}finally{
DBUtil.close(rs, stm, conn);
}
}
演示5:读一副图片到数据库
public static int addPhoto(){
int result=0;
Connection conn=null;
PreparedStatement stm=null;
try{
conn=DBUtil.getConn();
String sql="insert into t_testblob (name,photo) values (?,?)";
stm=conn.prepareStatement(sql); InputStream in=new BufferedInputStream(new FileInputStream("c://bigPhoto.bmp")); stm.setString(1, "大头鬼");
stm.setBinaryStream(2,in); result=stm.executeUpdate();
in.close(); }catch(Exception ex){
ex.printStackTrace();
}finally{
DBUtil.close(null, stm, conn);
}
return result;
}
附加:
图象或二进制文件 (Blob)
在mysql中,叫blob,在sqlserver中,叫 image 普通的blob 是64k。如果文件超过1M,则出现
Packet for query is too large (3781053 > 1048576). You can change this value on the server by setting the max_allowed_packet variable.
解决:
mysql 有一个系统参数 max_allowed_packet 默认值是 1048576(1M),
在my.ini中 , 找到 max_allowed_packet 它的值默认是 1M,可以将这个值调大。
演示六:使用配置文件
//在 DBUtil中设置
private static String url;
private static String user;
private static String password;
private static String className;
static{
try {
//读取配置文件
Properties settings =new Properties();
InputStream in=new FileInputStream("src/dbconfig.properties");
settings.load(in); url=settings.getProperty("url");
user=settings.getProperty("user");
password=settings.getProperty("password");
className=settings.getProperty("className"); System.out.println(url); Class.forName(className); //加载驱动类 //如果不导jar包 Could not initialize class util.DBUtil } catch (ClassNotFoundException | IOException e) {//在Java核心基础1中介绍,可以这样做
throw new RuntimeException(e);
}
}
Java JDBC的基础知识(四)的更多相关文章
- Java JDBC的基础知识(三)
在前面的Java JDBC的基础知识(二)和(三)中,主要介绍JDBC的原理和简单的应用过程.尤其在(二)中,可以发现代码进行多次try/catch,还有在前面创建连接等过程中好多参数我都给写定了. ...
- Java JDBC的基础知识(二)
在我的上一篇Java JDBC的基础知识(一)中,最后演示的代码在关闭资源的时候,仅仅用了try/catch语句,这里是有很大的隐患的.在程序创建连接之后,如果不进行关闭,会消耗更多的资源.创建连接之 ...
- Java JDBC的基础知识(五)
本文主要记录JDBC基础知识之后的部分内容.另外,我看到<Java核心基础2>中第四章是主要介绍数据库编程的.里面有一些说明和应用特别灵活,有些部分也太容易理解,建议大家看一下.这篇是依然 ...
- Java JDBC的基础知识(一)
一.为什么引入JDBC 在学习JDBC之前,抛开它的概念,我先按照我的理解解释一下,为什么要引入JDBC.在我看来,引入JDBC跟我之前学过的引入JVM(Java虚拟机)有些相似之处.当然,关于JVM ...
- JAVA核心技术I---JAVA基础知识(工具类Arrays和Collections类)
一:工具类 –不存储数据,而是在数据容器上,实现高效操作 • 排序 • 搜索 –Arrays类 –Collection类 二:Arrays类(处理数组) (一)基本方法 –排序:对数组排序, sort ...
- JAVA核心技术I---JAVA基础知识(static关键字)
一:static特殊关键字用处 –变量 –方法 –类 –匿名方法 二:静态变量:类共有成员 –static变量只依赖于类存在(通过类即可访问),不依赖于对象实例存在. –所有的对象实例,对于静态变量都 ...
- 【Java面试】基础知识篇
[Java面试]基础知识篇 Java基础知识总结,主要包括数据类型,string类,集合,线程,时间,正则,流,jdk5--8各个版本的新特性,等等.不足的地方,欢迎大家补充.源码分享见个人公告.Ja ...
- 第76节:Java中的基础知识
第76节:Java中的基础知识 设置环境,安装操作系统,安装备份,就是镜像,jdk配置环境,eclipse下载解压即可使用,下载tomcat 折佣动态代理解决网站的字符集编码问题 使用request. ...
- Java面试题-基础知识
参考文章:Java面试题-基础知识 基础能力 什么是值传递和引用传递 线程状态有哪些,它们之间是如何转换的 进程与线程的区别,进程间如何通讯,线程间如何通讯? HashMap的数据结构是什么?如何实现 ...
随机推荐
- dialog里屏蔽ESC和回车
重载PreTranslateMessage,在return之前加一句判断,只要是按下ESC和回车的消息,就直接置之不理即可,代码如下: if( pMsg->message == WM_KEYDO ...
- WPF ListBox的进阶使用(二)
项目中经常使用需要根据搜索条件查询数据,然后用卡片来展示数据.用卡片展示数据时,界面的宽度发生变化,希望显示的卡片数量也跟随变化.WrapPanel虽然也可以实现这个功能,但是将多余的部分都留在行尾, ...
- Entity Framework 6 多对多增改操作指南
问题描述 在很多系统中,存在多对多关系的维护.如下图: 这种多对多结构在数据库中大部分有三个数据表,其中两个主表,还有一个关联表,关联表至少两个字段,即左表主键.右表主键. 如上图,其中的Suppli ...
- AEAI DP开发统计分析
1 背景概述 平时做统计分析都是调rest服务,给前台提供数据,然后在管理控制台里配置portlet.但并不是所有的项目都会用到portal,这时就需要在AEAI DP应用开发平台里开发统计分析了,下 ...
- Google guava cache源码解析1--构建缓存器(3)
此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 下面介绍在LocalCache(CacheBuilder, CacheLoader)中调用的一些方法: Ca ...
- SAP接口的调用
最近做一个专案用到的SAO接口的调用,用到的上传参数获取回传的IRfcTable,以及以IRfcTable作为参数上传SAP,通过查阅很多资料,发现资料说明的也多是鱼龙混杂,许多没有实现就直接贴在上面 ...
- 《Python黑帽子:黑客与渗透测试编程之道》 玩转浏览器
基于浏览器的中间人攻击: #coding=utf-8 import win32com.client import time import urlparse import urllib data_rec ...
- iOS-【最新】跳转到 App Store 评分
APP应用内 App Store 跳转评分 NSString *itunesurl = @"itms-apps://itunes.apple.com/cn/app/id你的APPid?mt= ...
- Sentry有什么作用
Sentry是一个异常日志集中收集系统,它可以捕捉到 stack trace, stack locals, preceding events和引发该异常的commit号.而当bug fix后,sent ...
- MVC3学习:利用mvc3+ajax结合MVCPager实现分页
本例使用表格Users(Uid,UserName,PassWord),数据库访问使用EF first code. public class Users { [Key] public int Uid { ...