修改my.ini
[mysqld]
basedir = D:\develop\MySQL\mysql-5.7.31-winx64
datadir = D:\develop\MySQL\mysql-5.7.31-winx64\data
port = 3306
character-set-server=utf8
#设置时区
default-time-zone=timezone
default-time-zone = '+8:00'
#lower_case_table_names=0 表名存储为给定的大小和比较是区分大小写的
#lower_case_table_names = 1 表名存储在磁盘是小写的,但是比较的时候是不区分大小写
#lower_case_table_names=2 表名存储为给定的大小写但是比较的时候是小写的
lower_case_table_names = 1
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
安装
mysqld -install [名称,默认mysql]
启动服务
net start mysql
或
mysqld --console
无法启动情况下
mysqld --initialize-insecure
连接MySQL
// mysql [主机地址] -u[用户名] -p[密码];
mysql -uroot -p
修改密码
> use mysql;
> update user set password=PASSWORD('新密码') where user='用户名';
> flush privileges; #更新权限
> quit; #退出
关闭服务
net stop mysql
或
mysqladmin -uroot shudown
移除
mysqld -remove [名称]
[client]
loose_prompt=\\u@\\h \\d >
default-character-set=utf8
loose_default-character-set = utf8
[mysql]
default-character-set=utf8
查看当前数据库系统中的数据库列表
mysql>show databases;
使用DDL语句创建一个数据库mydb1
mysql> create database mydb1;
再次查看当前数据库列表
mysql> show databases;
切换至mydb1数据库
mysql> use mydb1;
查看当前数据库中的数据表
mysql> show tables;
使用DDL创建一个数据表
mysql> create table classes(clasid int, clasname varchar(30));
再次查看数据库中的数据表
mysql> show tables;
查看classes数据表结构
mysql> desc classes;
删除数据表
mysql> drop table classes;
删除数据库
mysql> drop database mydb1;
查询需要批量删除的表(模糊匹配)
SELECT CONCAT('drop table ', group_concat(TABLE_NAME), ';') FROM information_schema.`TABLES` WHERE table_schema = '数据库名' AND TABLE_NAME LIKE 'tab_%';
增加
INSERT INTO [表] VALUES([],[],[],[],[]);
INSERT INTO [表]([key1],[key2],...,[keyn])VALUES([],[],...,[]);
INSERT INTO [表]([key1],[key2],...,[keyn])VALUES([],[],...,[]),([],[],...,[]),...,([],[],...,[]);
删除
DELETE FROM [表] WHERE [id] = n;
修改
UPDATE [表]
SET
key1 = value,
key2 = value
sql = sql*n
WHERE [id] = n;
查找
*:所有
WHERE:条件判断
DISTINCT:不重复
BETWEEN n and m:在n和m之间
LIKE:模糊查询LIKE "%条件%"
SUBSTRING:查询第n位开始后m位为xx SUBSTRING(ename,n,m)='xx'
ORDER BY :默认情况下是升序;ASC 升序,DESC降序
SELECT * FROM tb_emp WHERE sal >=6000 ORDER BY sal ASC;
LIMIT:用来“截取”查询结果,常用于数据库的分页操作
-- LIMIT关键字后,只传一个参数时,从第一行开始取N条数据
SELECT * FROM tb_emp LIMIT 2;
-- 设置两个参数,第一参数代表起始位置(从0开始),第二个参数,从位置开始往后几条数据
SELECT * FROM tb_emp LIMIT 0,2; -- 第一条和第二条
聚合函数
-- 聚合函数 SUM(expr)求和 AVG([DISTINCT] expr) 求平均值
-- MAX(expr) 取最大 MIN(expr) 取最小 COUNT(DISTINCT expr,[expr...]) 计数
SELECT AVG(sal) FROM tb_emp WHERE ename = 'XH';
SELECT AVG(DISTINCT sal) FROM tb_emp;
SELECT MAX(sal) FROM tb_emp;
SELECT COUNT(1) FROM tb_emp;
GROUP BY 分组
SELECT * FROM tb_emp GROUP BY deptno;
SELECT AVG(sal),deptno FROM tb_emp GROUP BY deptno;
HAVING 关键字表示对分类后的结果再进行条件的过滤,经常会与WHERE进行对比
SELECT AVG(sal),deptno FROM tb_emp WHERE ename = 'XH' GROUP BY deptno HAVING AVG(sal) > 5000;
表关联,多表关联时,建议给表取别名
LEFT JOIN, 以左边表作为主表,附带显示其他关联的一些信息
SELECT * FROM tb_emp e
LEFT JOIN tb_dept d ON e.deptno = d.did;
--SELECT * FROM tb_emp e,tb_dept d ON e.deptno = d.did WHERE[];
SELECT e.*,d.* FROM tb_dept d
LEFT JOIN tb_emp e ON d.did = e.deptno;
内关联 ,关联两张表时,条件必须两边都满足,能用INNER JOIN 尽量优先适用
SELECT * FROM tb_emp e
INNER JOIN tb_dept d ON d.did = e.deptno;
RIGHT JOIN, 以右边表作为主表,进行查询操作
SELECT * FROM tb_emp e
RIGHT JOIN tb_dept d ON e.deptno = d.did;
笛卡儿积 员工表中4条,部门3条,查询结果12条
SELECT * FROM tb_emp e, tb_dept d;
SELECT * FROM tb_emp e, tb_dept d WHERE e.deptno = d.did;
SELECT * FROM tb_emp WHERE deptno = 10 OR deptno = 11;
-- 子查询结果是一个或多个值时,采用IN/NOT IN
SELECT * FROM tb_emp WHERE deptno IN (SELECT did FROM tb_dept);
SELECT * FROM tb_emp WHERE deptno NOT IN (SELECT did FROM tb_dept);
-- 子查询结果是一个值时,采用= 或 !=
SELECT * FROM tb_emp WHERE deptno = (SELECT did FROM tb_dept LIMIT 1);
-- select * from A where id in(select id from B)
-- SELECT * FROM A a WHERE EXISTS (SELECT * FROM B b WHERE b.id = a.id)
-- 导致效率差异的原因和索引有关系
-- IN()适合B表比A表数据小的情况
-- EXISTS()适合B表比A表数据大的情况
-- 当A表数据与B表数据差不多时,IN与EXISTS效率差不多,可任选一个使用.
-- NOT IN(不触发任何索引) 和 NOT EXISTS(触发索引)
SELECT * FROM tb_emp e
WHERE EXISTS (SELECT * FROM tb_dept d WHERE d.did = e.deptno);
SELECT * FROM tb_emp e
WHERE NOT EXISTS (SELECT * FROM tb_dept d WHERE d.did = e.deptno);
-- UNION ALL和UNION拼接多个查询结果,保证列的个数一致,UNION有做去重操作
SELECT * FROM tb_emp
UNION ALL
SELECT * FROM tb_emp;
SELECT * FROM tb_emp
UNION
SELECT * FROM tb_emp;
SELECT eid,sal FROM tb_emp
UNION ALL
SELECT * FROM tb_dept;
-- The used SELECT statements have a different number of columns
创建一个数据库用户z1,具有对数据库中所有表的SELECT/INSERT权限
GRANT SELECT,INSERT 数据库名.* TO 'cxl'@'localhost' IDENTIFIED BY '123'';
由于权限变更,需要将z1的权限变更,收回INSERT,只能对数据进行SELECT操作:
mysql -uroot
REVOKE INSERT ON 数据库名.* FROM 'cxl'@'localhost';
重新登录后执行前面的语句:
mysql -uz1 -p123
常用数值类型
TINYINT:1个字节
INT:4个字节
近似值存储
FLOAT:4个字节
DOUBLE:8个字节
DECIMAL(M,D)/DEC(M,D):常用于精度比较高的存储,例如:银行金额计算
日期类型
DATETIME:比较常用
面试点:DATETIME和timestamp区别
字符类型(面试点):
CHAR(M):长度固定,当字符长度没有达到M时,左补空格,常用于身份证号的设计
VARCHAR(M):长度可变,当字符长度没有达到M时,不做任何操作
concat(s1,s2,......sn) -- 连接s1,s2,.....,sn为一个字符串
insert(str,x,y,instr) -- 将字符串str从第x位置开始,y个字符长的子串替换为字符串instr
lower(str) -- 将字符串str中字符变为小写
upper(str) -- 将字符串str中字符变为大写
left(str,x) -- 返回字符串str最左边的x个字符
right(str,x) -- 返回字符串str最右边的x个字符
lpad(str,n,pad) -- 用字符串pad对str最左边进行填充,直到长度为n个字符长度
rpad(str,n,pad) -- 用字符串pad对str最右边进行填充,直到长度为n个字符长度
ltrim(str) -- 去掉字符串str左侧的空格
rtrim(str) -- 去掉字符串str右侧的空格
repeat(str,x) -- 返回str重复x次的结果
replace(str,a,b) -- 用字符串b替换字符串str中所有出现的字符串a
strcmp(s1,s2) -- 比较字符串s1和s2
trim(str) -- 去掉字符串行尾和行头的空格
substring(str,x,y) -- 返回从字符串str x位置起y个字符长度的字串
abs(x) -- 返回x的绝对值
ceil(x) -- 返回大于x的最小整数值
floor(x) -- 返回小于x的最大整数值
mod(x,y) -- 返回x/y的模
rand() -- 返回0~1内的随机值
round(x,y) -- 返回参数x的四舍五入的有y位小数的值
truncate(x,y) -- 返回数字x截断为y位小数的结果
curdate() -- 返回当前日期
curtime() -- 返回当前时间
now() -- 返回当前的日期和时间
unix_timestamp(date) -- 返回日期date的unix时间戳
from_unixtime -- 返回unix时间戳的日期值
week(date) -- 返回日期date为一年中的第几周
year(date) -- 返回日期date的年份
hour(time) -- 返回time的小时值
minute(time) -- 返回time的分钟值
monthname(date) -- 返回日期date的月份名
date_format(date,fmt) -- 返回按字符串fmt格式化日期datee值
date_add(date,interval expr type) -- 返回一个日期或时间值加上一个时间间隔的时间值
datediff(expr,expr2) -- 返回起始时间expr和结束时间expr2之间的天数
MySQL支持的日期和时间格式:
%d -- 两位数字表示月中的天数(00,01,...,31)
%e -- 数字形式表示月中的天数(00,01,...,31)
%D -- 英文后缀表示月中的天数(1st,2nd,3rd,...)
%w -- 以数字形式表示周中的天数(0=Sunday,1=Monday,...,6=Saturday)
%j -- 以3位数字表示年中的天数(001,002,...,366)
%U -- 周(0,1,52),其中Sunday为周中的第一天
%u -- 周(0,1,52),其中Monday为周中的第一天
%M -- 月名(January,February,...,December)
%b -- 缩写的月名
%m -- 两位数字表示的月份(01,02,...,12)
%c -- 数字表示的月份(1,2,...,12)
%Y -- 4位数字表示的年份
%y -- 两位数字表示的年份
%% -- 直接值“%”
hour -- 小时 -- hh
minute -- 分 -- mm
second -- 秒 -- ss
year -- 年 -- YY
month -- 月 -- MM
day -- 日 -- DD
year_month -- 年和月 -- YY-MM
day_hour -- 日和小时 -- DD hh
day_minute -- 日和分钟 -- DD hh:mm
day_second -- 日和秒 -- DD hh:mm:ss
hour_minute -- 小时和分 -- hh:mm
hour_second -- 小时和秒 -- hh:ss
minute_second -- 分钟和秒 -- mm:ss
if(value,t,f) -- 如果value是真,返回t;否则返回f
ifnull(value1,value2) -- 如果value1不为空,返回value1,否则value2
case when[value1] then [result]...else [default] end -- 如果value1是真,返回result,否则返回default
case [expr] when [value1] then [result1] ... else
[default] end -- 如果expr等于value1,返回result1,否则返回default
索引:它是SQL优化的重要手段之一,相当于书本的目录,根据目录页码快速找到所需的内容,索引是单独的,物理的对数据库中一列或多列的值进行排序的一种存储结构。
注意:索引并不是添加的越多越好,索引并不是添加之后就一定会触发。
-- 使用CREATE INDEX创建索引
CREATE [UNIQUE] INDEX INDEX_索引名 ON 表名(字段);
-- 使用ALTER TABLE创建索引
ALTER TABLE 表名 ADD INDEX INDEX_索引名(字段); -- 普通索引
ALTER TABLE 表名 ADD UNIQUE (字段); -- 唯一约束
ALTER TABLE 表名 ADD PRIMARY KEY (字段) -- 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。
-- 验证索引被启用的情况
EXPLAIN SELECT 字段 FROM 表名;
-- 显示索引信息
SHOW INDEX FROM 表名;
SHOW KEYS FROM 表名;
-- 创建复合索引
CREATE INDEX INDEX_索引名 ON 表名(字段1,字段2);
-- 删除索引
DROP INDEX INDEX_索引名 ON 表名;
ALTER TABLE 表名 DROP INDEX INDEX_索引名;
ALTER TABLE 表名 DROP PRIMARY KEY;
索引分类:
普通索引、复合索引、唯一索引、主键、全文检索
那些场景适合添加索引?
经常接在WHERE后作为查询条件
表关联时,关联的字段
字段唯一,可以添加唯一索引
表中数据重复性不是非常高
经常更新的字段不建议构建索引
查询显示的列名不需要加索引
如果查询时,多个字段经常被查询,建议适用复合索引
那些场景不适合添加索引?
经常更新的字段不建议构建索引
表中数据重复率太高,例如:性别
一般情况下,表中添加普通索引和复合索引居多,唯一和主键,主较特殊的;
注意:复合索引需要遵循最左原则
最左原则:(a,b,c),有效索引 a / a,b / a,b,c
索引失效的情况:
并没有将加了索引的字段作为条件
字段定义的是字符类型,查询时需要添加’ ’
模糊查询时 LIKE ‘%ABC%’ ,但是 LIKE ‘ABC%’ 可以触发索引
查询条件采用了OR关键字
针对复合索引,没有遵循最左原则
应用了一些函数,也会导致索引失效
MySQL中如何查看索引是否触发?
借助EXPLAIN关键字执行SQL语句
possible_key:可能会触发的索引
key:触发的索引
rows:估算的结果数据行
Extra:执行具体描述
BTREE索引和HASH索引的区别?
HASH索引满足等值查询,效率非常高
BTREE索引查询数据时比较适用于范围的查找,例如:<> 、ORDER BY 等场景比较适用
一张虚拟的表,它是由SQL语句查询结果组成的一个数据集,常用于频繁使用某些SQL语句,将他们构成一个视图。
视图经常用于查询操作,比较少也会用于更新操作(增/删/改),在更新操作时,需要注意,并不是所有的视图都可以进行更新操作,例如:表关联查询、采用聚合函数、DISTINCT、GROUP BY、HAVING、UNION、UNION ALL、子查询等等。
CREATE [OR REPLACE] VIEW v_name
AS SELECT ......;
-- 查看视图定义
SHOW CREATE VIEW v_name;
-- 显示视图的信息
SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern'];
-- 查看视图设计信息
DESCRIBE | DESC v_name;
SHOW FIELDS FROM v_name;
DROP VIEW [IF EXISTS] v_name[,view_name];
在对某一张表进行更新(增/删/改)操作,执行触发器中定义语句集合。
特性:
建议:少用触发器;原因:效率问题,隐式操作等
触发器构建:
-- 构建触发器
CREATE TRIGGER <触发器名> < BEFORE | AFTER >
<INSERT | UPDATE | DELETE >
ON <表名> FOR EACH ROW<触发器主体>
-- 查看创建的触发器
SHOW TRIGGERS;
-- 删除触发器
DROP TRIGGER [ IF EXISTS ] [数据库名] <触发器名>
触发器主体:可以是SQL语句集,即可以是一条或n条SQL语句;当是n条SQL,需采用 BEGIN END 代码块,类似于java中的{ },还需要注意结束符号问题,MySQL默认结束符号为分号(;),可以采用 DELIMITER 关键字对结束符号进行修改,例如:$$
触发器中的OLD和NEW:
注意:触发器是附在表上来进行定义的,触发内容不可以操作当前表
-- 复制表的结构及数据,主键、索引没能够复制
CREATE TABLE 新表 SELECT * FROM 旧表;
-- 完整复制表的结构、主键、索引,未曾复制数据
CREATE TABLE 新表 LIKE 旧表;
INSERT INTO 新表 SELECT * FROM 旧表; -- 数据复制
SQL语句集,也可以写一些业务内容
注意:
=是判断
:=是赋值
=只有在set和update时才是和:=一样
赋值操作时
语法:
-- 创建
CREATE PROCEDURE pro_name(IN|OUT|INOUT 参数名 参数类型)
BEGIN
routine_body
END;
-- 调用
CALL sp_name(parms)
-- 删除
DROP PROCEDURE pro_name
定义变量:DECLARE 参数名 参数类型 [DEFAULT 默认值]
赋值:SELECT 字段 INTO 参数名 FROM 表 WHERE 条件
输出:SELECT 参数名
IF 条件1 THEN 操作1;
[ELSEIF 条件2 THEN 操作2]...
[ELSE 操作3];
END IF;
CASE 变量
WHEN 值1 THEN
操作1;
[WHEN 值2 THEN 操作2]...
[ELSE 操作3]
END CASE;
name_loop:LOOP
执行语句块;
-- 出循环
IF 条件1 THEN
LEAVE name_loop;
END IF;
END LOOP;
WHILE 条件
DO 执行语句块;
END WHILE;
REPEAT
执行语句块;
UNTIL 判定
END REPEAT;
-- 自定义函数
CREATE FUNCTION 函数名(变量 类型)
RETURNS 返回类型
BEGIN
RETURN ();
END;
-- 调用函数
SELECT 函数名(变量);
-- 删除函数
DROP FUNCTION 函数名;
游标/光标
CREATE PROCEDURE pro_name()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- 声明光标:
DECLARE 光标名 CURSOR FOR [SELECT语句];
-- DECLARE cur1 CURSOR FOR SELECT empno,sal FROM t_employee;
-- OPEN光标:
OPEN 光标名;
name_loop:LOOP
-- 出循环
IF done THEN
LEAVE name_loop;
END IF;
-- FETCH光标: 下移
FETCH [[NEXT] FROM] cursor_name INTO var_name[,var_name]...;
END LOOP;
-- CLOSE光标:
CLOSE 光标名;
END;
BEGIN:开启事务
事务的特征:ACID,
原子性(Atomicity)、一致性(Correspondence)、隔离性(Isolation)、持久性(Durability)。
原子性:事务中所有的操作视为一个原子单元,所有操作完全提交(成功)或完全回滚(失败)
一致性:事务完成后,所有数据从一种状态变更为另一种状态,确保数据完整性
隔离性:事务和事务之间有一定隔离
持久性:事务完成后,所做更新操作对数据影响是永久的
隔离级别:
READ-UNCOMMITTED:读取未提交内容。(容易发生脏读)
READ-COMMITTED:读取提交内容。(可能发生不可重复读、幻读)
REPEATABLE-READ:可重复读
SEIALIZABLE:可串行化
查看当前隔离级别;
SHOW VARIABLES LIKE 'tx_isolation';
设置隔离级别
-- 读取未提交
SET GLOBAL TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED];
脏读:某一个事务已更新一份数据,另一个事务读取了同一份数据,由于某些原因,导致前一个事务回滚操作,后面的事务读取的数据不正确。
不可重复读:在一个事务的两次査询数据不一致,这可能是两次查询过程中,另一个事务更新原有的数据。
幻读:在一个事务中两次查询数据条数不一致,例如:在一个事务中查询了几列值,另一个事务此时插入了几条新数据,先前的事务再次查询时,就发现多了几条数据是没有的。
public class JdbcUtil {
private static final String url = "jdbc:mysql://localhost:3306/数据库";
private static final String user = "root";
private static final String password = "";
public static Connection getConn() throws ClassNotFoundException, SQLException {
// 1. 加载驱动,通过反射 Maven
Class.forName("com.mysql.jdbc.Driver");
// 2.连接数据库
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
public static void close(ResultSet rs , PreparedStatement pstmt, Connection conn) {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(PreparedStatement pstmt, Connection conn) {
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
public class BaseDao<T> {
private Class<T> clazz;
@SuppressWarnings("unchecked")
public BaseDao() {
// 得到当前类的带有泛型信息的父类型
Type type = this.getClass().getGenericSuperclass();
// 得到实际的泛型参数类型
ParameterizedType pType = (ParameterizedType) type;
clazz = (Class<T>) pType.getActualTypeArguments()[0];
}
/**
* 查询
*
* @param sql
* @param params
* @return
* @throws Exception
*/
public List<T> find(String sql, Object[] params) throws Exception {
PreparedStatement psmt = null;
ResultSet rs = null;
// 连接数据库
Connection conn = JdbcUtil.getConn();
// 预编译SQL
psmt = conn.prepareStatement(sql);
// 通过循环动态设定参数
if (params != null) {
for (int i = 0; i < params.length; i++) {
psmt.setObject(i + 1, params[i]);
}
}
// 执行SQL语句
rs = psmt.executeQuery();
// 获取列相关信息
ResultSetMetaData rsmd = rs.getMetaData();
// 查询多少列
int colCount = rsmd.getColumnCount();
List<T> dataList = new ArrayList<T>();
while (rs.next()) {
// 采用反射实例化对象
T t = (T) clazz.newInstance();
// 返回Employee类的BeanInfo对象
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
// 使用BeanInfo返回属性描述的对象数组
PropertyDescriptor[] propDescs = beanInfo.getPropertyDescriptors();
for (int i = 1; i <= colCount; i++) {
String colName = rsmd.getColumnName(i);
for (PropertyDescriptor prop : propDescs) {
// 当列名和属性名一致的时候
if (colName.equals(prop.getName())) {
// 执行是属性对应的Setter方法
prop.getWriteMethod().invoke(t, rs.getObject(i));
continue;
}
}
}
dataList.add(t);
}
JdbcUtil.close(rs, psmt, conn);
return dataList;
}
/**
* 更新共通
* @param sql
* @param params
* @return
* @throws Exception
*/
public int update(String sql, Object[] params) throws Exception {
PreparedStatement psmt = null;
// 连接数据库
Connection conn = JdbcUtil.getConn();
// 预编译SQL
psmt = conn.prepareStatement(sql);
// 通过循环动态设定参数
if (params != null) {
for (int i = 0; i < params.length; i++) {
psmt.setObject(i + 1, params[i]);
}
}
return psmt.executeUpdate();
}
}
String sql = "SELECT * FROM commodity WHERE cid = ?";
Object[] param = {pid};
List<Product> list = pd.find(sql, param);
for (Product product : list) {
System.out.println(product);
}
String sql = "INSERT INTO car(uid,create_time) VALUES (?,NOW());";
Object[] param = {pid};
int flat = pd.update(sql, param);
if (flat==1) {
System.out.println("已选择该商品");
}
public class JdbcCommon {
public List<?> find(String sql,Object[] params) throws Exception{
PreparedStatement psmt = null;
ResultSet rs = null;
//连接数据库
Connection conn = JdbcUtil.getConn();
//预编译
psmt = conn.prepareStatement(sql);
//通过循环动态设定参数
if (params!=null) {
for (int i = 0; i < params.length; i++) {
psmt.setObject(i+1, params[i]);
}
}
//执行SQL语句
rs = psmt.executeQuery();
List<Map<String, Object>> dataList = new ArrayList<>();
//获取列相关信息
ResultSetMetaData rsmd = rs.getMetaData();
//查询多少列
int colCount = rsmd.getColumnCount();
while (rs.next()) {
Map<String, Object> map = new HashMap<String, Object>();
for (int i = 0; i < colCount; i++) {
map.put(rsmd.getColumnName(i), rs.getObject(i));
}
dataList.add(map);
}
JdbcUtil.close(rs, psmt, conn);
return dataList;
}
}