0%

2017年9月4日 下午4:56

概述:

封装的效果:在逻辑层中,能够通过一个简单的sql语句,就可以拿到一个list对象,这个list对象中包含了自己要查询的数据
改进:在起到封装的效果之后,我们可以在对数据库连接的效率进行优化。因为,当我们每次对一条sql语句进行查询的时候,我们要新建一次与数据库的连接,然后再断开连接。这样周而复始,其实是很浪费数据库资源的,尤其是多用户同时操作数据库时。所以,我们能不能这连接进行复用,而不是一次性的?
改进参考:两种数据库连接池 (2017/9/5)

属性配置文件

建File类型文件 最后起名的时候加上.properties

引用属性配置文件(static)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
* 静态代码块 类加载时完成数据初始化
*/
static {
Properties p = new Properties();
try {
p.load(DbUtils.class.getClassLoader().getResourceAsStream("com/shanxi/properties/dbUtils.properties"));
driverUrl = p.getProperty("driverUrl");
url = p.getProperty("url");
username = p.getProperty("username");
password = p.getProperty("password");
} catch (IOException e) {
e.printStackTrace();
}
}

注意:这里的属性文件的位置,要写全

完整的DbUtiles类 + 属性配置

写这个封装类,学到了以下几点

  1. 如何处理输入数据
    1. 这里要转换成数组输入
  2. 如何处理输出数据
    1. 这要转换成list类型输出
  3. 说白了,其实就是各种类型之间的转换
    1. 转成数组类型
    2. 转成list类型
    3. 转成map类型
    4. 转成字符串类型
    5. 转成其他范式集合类型
    6. 常见的就以上几种

附录代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
package com.shanxi.dbUtils;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;


/*
* 数据库工具类
*/
public class DbUtils {
//数据库连接对象 Connection
private static Connection conn;
//操作数据库对象Statement
private static Statement sta;
//操作数据库预编译对象Preparstatement
private static PreparedStatement ps;
//驱动类地址
private static String driverUrl;
//URL数据库连接
private static String url;
//用户名
private static String username;
//密码
private static String password;
/*
* 静态代码块 类加载时完成数据初始化
*/
static {
Properties p = new Properties();
try {
p.load(DbUtils.class.getClassLoader().getResourceAsStream("com/shanxi/properties/dbUtils.properties"));
driverUrl = p.getProperty("driverUrl");
url = p.getProperty("url");
username = p.getProperty("username");
password = p.getProperty("password");
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* 获取Connection连接的方法
* @return conn
*/
public static Connection getConnection() {
try {
Class.forName(driverUrl);
conn = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}

/*
* 不支持预编译的查询方法
*/
public static List<Map<String,Object>> queryForList(String sql){
List<Map<String,Object>> list = new ArrayList<Map<String, Object>>();
try {

conn = getConnection();
sta = conn.createStatement();
ResultSet rs = sta.executeQuery(sql);
list = rsToList(rs);
close();

} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
/*
* 不支持预编译的增删改方法
*/
public static int excuteUpdate(String sql){

return 0;
}

/*
* 支持预编译的查询方法
*/
public static List<Map<String,Object>> queryForList(String sql,int[] type,Object[] obj){
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
//循环遍历参数数组 并将数组中的值设置给预编译sql
for (int i = 0; i < obj.length; i++) {
switch (type[i]) {
case Types.INTEGER:
ps.setInt(i+1,Integer.parseInt(obj[i].toString()));
break;
case Types.VARCHAR:
ps.setString(i+1,obj[i].toString());
break;
default:
ps.setString(i+1,obj[i].toString());
}
}
ResultSet rs = ps.executeQuery();
list = rsToList(rs);
close();

} catch (SQLException e) {
e.printStackTrace();
}

return list;
}
/*
* 支持预编译的增删改方法
*/
public static int excuteUpdate(String sql,int[] type,Object[] obj){

return 0;
}

/*
* 不支持预编译的计数查询方法
*/
public static int queryForCount(String sql){


return 0;
}

/*
* 支持预编译的计数查询方法
*/

public static int queryForCount(String sql,int[] type,Object[] obj){


return 0;
}

/*
* 将resultSet结果集转换为List
* @param rs 封装数据的resultSet
* @return 数据转换后的List
*/
private static List<Map<String, Object>> rsToList(ResultSet rs) {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

try {
while(rs.next()){
Map<String, Object> map = new HashMap<String,Object>();
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
switch (rs.getMetaData().getColumnType(i)) {
case Types.INTEGER:
map.put(rs.getMetaData().getColumnName(i),rs.getInt(i));
break;
case Types.VARCHAR:
map.put(rs.getMetaData().getColumnName(i),rs.getString(i));
break;
default:
map.put(rs.getMetaData().getColumnName(i),rs.getObject(i));
}
}
list.add(map);
}
} catch (SQLException e) {
e.printStackTrace();
}

return list;
}

/*
* 关闭Connection连接的方法
*/
public static void close(){
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
System.gc();
}
}
}
}


public static void main(String[] args) {

List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
//测试非预编译方法
// String sql ="select * from people";
// list = DbUtils.queryForList(sql);
// for (Map<String, Object> map : list) {
// System.out.println(map.get("name")+"---"+map.get("age"));
// }
//测试预编译对象
String sql1 ="select * from people where age = ? and sex= ? and salary >?";
int [] type = {Types.INTEGER,Types.VARCHAR,Types.FLOAT};
Object[] obj = {20,"男",3500};
list = DbUtils.queryForList(sql1,type,obj);
for (Map<String, Object> map : list) {
System.out.println(map.get("name")+"---"+map.get("age"));
}
}
}

注:这个没有写完

1
2
3
4
5
6
7
8
9
10
#driverUrl=com.mysql.jdbc.Driver
#url =jdbc:mysql://localhost:3306/test4?useUnicode=true&characterEncoding=utf8
#username=root
#password=root


driverUrl=oracle.jdbc.driver.OracleDriver
url =jdbc:oracle:thin:@192.168.42.43:1521:orcl
username=gao
password=gao

2017年9月4日 下午2:37

乱码

  1. 当我们从jdbc中插入数据库的值为乱码时,要查看当前project的编码方式(从propertise),如下图(这里是UTF-8)。
  2. 如果数据库的编码是UTF-8,而project的编码是gbk,那么就会出现插入的数据库信息乱码。

#web开发/czh_blog/数据库
2017年9月1日 上午10:36

这里知识理解一些概念,有一个基本的认识
知道ORACLE支持哪些功能,以后一个功能呢不好做的时候,来这里瞧瞧,看有没有正好能用上额特性

PLSQL中语法特别的地方

没有逻辑修饰符:|| &&
用这些代替:And or between
等号:是:= 不是=
没有:++ — —
|| 内容拼接 隐式转换成字符串连接

SQL的高级语言特性PLSQL

  1. 所谓的plsql其实就是:sql编程语言一样编程,有高级语言的特性
  2. If switch for loop
  3. Cursor游标 是专门用来解决表中多条数据的情况
    1. 这个高级语言中没有,是数据库语言中特有的
    2. 和loop连用
  4. 类似stl的数据类型
    1. Varray
    2. table
    3. record
  5. 自定义数据类型
    1. type
  6. 异常
    1. 支持自定义抛出异常
      1. 当在函数和存储过程中抛出异常时,可以在调用函数和存储过程的外面进行异常的处理
    2. 支持选择自己处理异常,和oracle系统处理异常
      1. 当没有写exception段时,默认就是让oracle处理异常
  7. package
    1. 这个就是java中的类,不是java中的包
    2. 可以在package中和java一样定义变量,常量,函数(存储过程+函数)等等
    3. packages + package body
    4. 如何操作
      1. 不是java中的先new一个对象,然后用对象调用
      2. Sql中没有new对象,直接使用package名 点就行了

存储过程的构成

  1. 给PLSQL去了个名字方便调用
  2. 存储过程
  3. 传入参数
  4. 传出参数

为什么要封装成存储过程?

  1. 封装之后方便传入传出参数
  2. 匿名块只能在数据库环境中调用 存储过程可以被外界调用(比如JDBC)

函数与存储过程比较:

  1. 函数可以看做一类特殊的存储过程 没有输出参数 必有唯一返回值
  2. 删掉输出参数,添加返回值
  3. 存储过程可以完全的实现函数的功能

如何选择函数与存储过程

  1. 当PL-SQL需要嵌在SQL中使用时用函数
    1. 就像min() max() count()这些函数
  2. 当有多个返回值或者要被其它程序调用时用存储过程

既然利用PLSQL可以实现高级语言的特性,那么当我们实现一个功能的时候,有哪些不同的、或者值得注意的地方

需求:利用存储过程查询含有特定信息的学生id
思路:

  1. 也就是说这个参数可以是学生姓名,生日,电话号等等信息。在java中我们需要对这个特定信息进行判断,写上一堆if,但是在sql中我直接写在where语句中就行了,就省去了判断的过程
  2. 体现了sql的优势,对比与java语言

触发器

  1. 使用触发器的环境:
    1. 业务逻辑是多步骤的 而且可能从任意一个步骤执行 一般用触发器链
    2. 传进来的参数 是一行数据 一般用触发器
  2. 有了存储过程 为什么还要用触发器
    1. 存储过程需要特殊的调用方式
    2. A -> B -> c -> D->
      1. 连锁操作的业务逻辑 用触发器,JDBC只要正常的SQL语句
  3. 触发器要注意的地方
    1. 暂时用不到的触发器全部禁用
      1. 使用disable
    2. 避免逻辑死锁
      1. 一个trigger就是一个线程
      2. 那么,不说自己的创建的线程,光是系统中默认的操作表的线程就有可能和自己的一个trigger线程产生冲突
    3. 尽量避免update触发器中对本表的操作

Sequence 就像一个全局int型变量,他可以一直记录一个变量的值



百度


Mac下不用虚拟机一样可以使用PLSQL Developer - iCoding91 - CSDN博客

%符号 理解成“的”

#web开发/czh_blog/数据库
2017年9月1日 上午10:36

这里知识理解一些概念,有一个基本的认识
知道ORACLE支持哪些功能,以后一个功能呢不好做的时候,来这里瞧瞧,看有没有正好能用上额特性

PLSQL中语法特别的地方

没有逻辑修饰符:|| &&
用这些代替:And or between
等号:是:= 不是=
没有:++ — —
|| 内容拼接 隐式转换成字符串连接

SQL的高级语言特性PLSQL

  1. 所谓的plsql其实就是:sql编程语言一样编程,有高级语言的特性
  2. If switch for loop
  3. Cursor游标 是专门用来解决表中多条数据的情况
    1. 这个高级语言中没有,是数据库语言中特有的
    2. 和loop连用
  4. 类似stl的数据类型
    1. Varray
    2. table
    3. record
  5. 自定义数据类型
    1. type
  6. 异常
    1. 支持自定义抛出异常
      1. 当在函数和存储过程中抛出异常时,可以在调用函数和存储过程的外面进行异常的处理
    2. 支持选择自己处理异常,和oracle系统处理异常
      1. 当没有写exception段时,默认就是让oracle处理异常
  7. package
    1. 这个就是java中的类,不是java中的包
    2. 可以在package中和java一样定义变量,常量,函数(存储过程+函数)等等
    3. packages + package body
    4. 如何操作
      1. 不是java中的先new一个对象,然后用对象调用
      2. Sql中没有new对象,直接使用package名 点就行了

存储过程的构成

  1. 给PLSQL去了个名字方便调用
  2. 存储过程
  3. 传入参数
  4. 传出参数

为什么要封装成存储过程?

  1. 封装之后方便传入传出参数
  2. 匿名块只能在数据库环境中调用 存储过程可以被外界调用(比如JDBC)

函数与存储过程比较:

  1. 函数可以看做一类特殊的存储过程 没有输出参数 必有唯一返回值
  2. 删掉输出参数,添加返回值
  3. 存储过程可以完全的实现函数的功能

如何选择函数与存储过程

  1. 当PL-SQL需要嵌在SQL中使用时用函数
    1. 就像min() max() count()这些函数
  2. 当有多个返回值或者要被其它程序调用时用存储过程

既然利用PLSQL可以实现高级语言的特性,那么当我们实现一个功能的时候,有哪些不同的、或者值得注意的地方

需求:利用存储过程查询含有特定信息的学生id
思路:

  1. 也就是说这个参数可以是学生姓名,生日,电话号等等信息。在java中我们需要对这个特定信息进行判断,写上一堆if,但是在sql中我直接写在where语句中就行了,就省去了判断的过程
  2. 体现了sql的优势,对比与java语言

触发器

  1. 使用触发器的环境:
    1. 业务逻辑是多步骤的 而且可能从任意一个步骤执行 一般用触发器链
    2. 传进来的参数 是一行数据 一般用触发器
  2. 有了存储过程 为什么还要用触发器
    1. 存储过程需要特殊的调用方式
    2. A -> B -> c -> D->
      1. 连锁操作的业务逻辑 用触发器,JDBC只要正常的SQL语句
  3. 触发器要注意的地方
    1. 暂时用不到的触发器全部禁用
      1. 使用disable
    2. 避免逻辑死锁
      1. 一个trigger就是一个线程
      2. 那么,不说自己的创建的线程,光是系统中默认的操作表的线程就有可能和自己的一个trigger线程产生冲突
    3. 尽量避免update触发器中对本表的操作

Sequence 就像一个全局int型变量,他可以一直记录一个变量的值



百度


Mac下不用虚拟机一样可以使用PLSQL Developer - iCoding91 - CSDN博客

%符号 理解成“的”

2017年9月1日 下午5:44

ORACLE SQL Developer
Navticat premium
PL/SQL

  1. 我觉得最好的是ORACLE SQL Developer
  2. 这个是oracle官方出的Oracle SQL Developer Downloads
  3. 可以支持多系统,包括mac
  4. 官方手册使用 SQL Developer 开发和调试 PL/SQL
  5. 左侧有各种功能支持,右击就可以
    1. 他的使用和PL_SQL差不多,但是界面美化比PL_SQL好多了
    2. 与navicat相比,navicat毕竟不是亲生的,左侧功能的支持不好,比如package


可以看出他们可以同时连接
但是在navicat中添加的数据,在PL/SQL中会乱码
plsql查询数据显示为乱码解决方法 - aovenus的专栏 - CSDN博客

#web开发/czh_blog/数据库
2017年8月31日 上午11:03

连接有哪些

  1. 固定的:外键连接
  2. 额外的:看自己有啥要求,或者要过滤那些情况
    1. 关键是要明白自己的需求
    2. 然后转换成里逻辑表达式

#web开发/czh_blog/数据库
2017年8月31日 上午11:03

连接有哪些

  1. 固定的:外键连接
  2. 额外的:看自己有啥要求,或者要过滤那些情况
    1. 关键是要明白自己的需求
    2. 然后转换成里逻辑表达式

#web开发/czh_blog/数据库
2017年8月31日 上午9:51

关于聚合函数注意事项

原则:select中的每一项,单独查询的话结果条数相等
技巧:当没有group by 使用聚合函数最有可能出问题



查询student表中的男生
一共四个男生,对应四条数据



查询student表中的男生人数
男生人数是4,就一条数据



当同时查询男生人数,和男生时
就会造成1对4 表就不知道怎么表示了

修改为下图也可以