Windows的Mysql5.7安装及使用

余天宇
2023-12-01

1、安装MySQL

  • 修改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

2、操作语句

1、DDL语句完成数据库及数据表的创建

  1. 查看当前数据库系统中的数据库列表

    mysql>show databases;
    
  2. 使用DDL语句创建一个数据库mydb1

    mysql> create database mydb1;
    
  3. 再次查看当前数据库列表

    mysql> show databases;
    
  4. 切换至mydb1数据库

    mysql> use mydb1;
    
  5. 查看当前数据库中的数据表

    mysql> show tables;
    
  6. 使用DDL创建一个数据表

    mysql> create table classes(clasid int, clasname varchar(30));
    
  7. 再次查看数据库中的数据表

    mysql> show tables;
    
  8. 查看classes数据表结构

    mysql> desc classes;
    
  9. 删除数据表

    mysql> drop table classes;
    
  10. 删除数据库

    mysql> drop database mydb1;
    
  11. 查询需要批量删除的表(模糊匹配)

    SELECT CONCAT('drop table ', group_concat(TABLE_NAME), ';') FROM information_schema.`TABLES` WHERE table_schema = '数据库名' AND TABLE_NAME LIKE 'tab_%';
    

2、DML增删改查

  1. 增加

    INSERT INTO [表] VALUES([],[],[],[],[]);
    INSERT INTO [表]([key1],[key2],...,[keyn])VALUES([],[],...,[]);
    INSERT INTO [表]([key1],[key2],...,[keyn])VALUES([],[],...,[]),([],[],...,[]),...,([],[],...,[]);
    
  2. 删除

    DELETE FROM [表] WHERE [id] = n;
    
  3. 修改

    UPDATE [表]
    SET
    	key1 = value,
    	key2 = value
    	sql = sql*n
    WHERE [id] = n;
    
  4. 查找

    1. *:所有

    2. WHERE:条件判断

    3. DISTINCT:不重复

    4. BETWEEN n and m:在n和m之间

    5. LIKE:模糊查询LIKE "%条件%"

    6. SUBSTRING:查询第n位开始后m位为xx SUBSTRING(ename,n,m)='xx'

    7. ORDER BY :默认情况下是升序;ASC 升序,DESC降序

      SELECT * FROM tb_emp WHERE sal >=6000 ORDER BY sal ASC;
      
    8. LIMIT:用来“截取”查询结果,常用于数据库的分页操作

      -- LIMIT关键字后,只传一个参数时,从第一行开始取N条数据
      SELECT * FROM tb_emp LIMIT 2;
      -- 设置两个参数,第一参数代表起始位置(从0开始),第二个参数,从位置开始往后几条数据
      SELECT * FROM tb_emp LIMIT 0,2; -- 第一条和第二条
      
    9. 聚合函数

      -- 聚合函数 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;
      
    10. GROUP BY 分组

      SELECT * FROM tb_emp GROUP BY deptno;
      SELECT AVG(sal),deptno FROM tb_emp GROUP BY deptno;
      
    11. HAVING 关键字表示对分类后的结果再进行条件的过滤,经常会与WHERE进行对比

      SELECT AVG(sal),deptno FROM tb_emp WHERE ename = 'XH' GROUP BY deptno HAVING AVG(sal) > 5000;
      
    12. 表关联,多表关联时,建议给表取别名

      1. 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;
        
      2. 内关联 ,关联两张表时,条件必须两边都满足,能用INNER JOIN 尽量优先适用

        SELECT * FROM tb_emp e
        INNER JOIN tb_dept d ON d.did = e.deptno;
        
      3. RIGHT JOIN, 以右边表作为主表,进行查询操作

        SELECT * FROM tb_emp e
        RIGHT JOIN tb_dept d ON e.deptno = d.did;
        
      4. 笛卡儿积 员工表中4条,部门3条,查询结果12条

        SELECT * FROM tb_emp e, tb_dept d;
        
        SELECT * FROM tb_emp e, tb_dept d WHERE e.deptno = d.did;
        
      5. 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
        

3、DCL

创建一个数据库用户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

3、常用类型

  • 常用数值类型

    TINYINT:1个字节

    INT:4个字节

    • 近似值存储

      FLOAT:4个字节

      DOUBLE:8个字节

      DECIMAL(M,D)/DEC(M,D):常用于精度比较高的存储,例如:银行金额计算

  • 日期类型

    DATETIME:比较常用

    面试点:DATETIME和timestamp区别

  • 字符类型(面试点):

    CHAR(M):长度固定,当字符长度没有达到M时,左补空格,常用于身份证号的设计

    VARCHAR(M):长度可变,当字符长度没有达到M时,不做任何操作

4、常用函数

a.字符串函数

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个字符长度的字串

b.数值函数

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位小数的结果

c.日期和时间函数

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

d.流程函数

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

5、约束

  1. NOT NULL:非空
  2. DEFAULT:默认值
  3. PRIMARY KEY:主键,唯一且非空。
  4. UNIQUE:唯一,可以为空
  5. CHECK:检查约束(MySQL不支持)
  6. FOREIGN KEY:外键,把一个字段关联到另一个表的主键

6、索引

索引:它是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索引的区别?

    1. HASH索引满足等值查询,效率非常高

    2. BTREE索引查询数据时比较适用于范围的查找,例如:<> 、ORDER BY 等场景比较适用

7、视图

一张虚拟的表,它是由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];

8、触发器

在对某一张表进行更新(增/删/改)操作,执行触发器中定义语句集合。

  • 特性:

    • 触发条件:INSERT \ DELETE \ UPDATE
    • 触发时机:AFTER / BEFORE
    • 触发频率:针对每一行执行
  • 建议:少用触发器;原因:效率问题,隐式操作等

  • 触发器构建:

    -- 构建触发器
    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:

  1. 在INSERT型触发器中,NEW用来表示新插入的数据,不管是BEFORE 还是 AFTER
  2. 在UPDATE型触发器中,OLD用来表示已经被修改掉或即将被修改的数据,NEW用来表示即将要修改或者已经修改了的数据。
  3. 在DELETE型触发器中,OLD用来表示即将删除或已经被删除的原数据

注意:触发器是附在表上来进行定义的,触发内容不可以操作当前表

表复制操作:

-- 复制表的结构及数据,主键、索引没能够复制
CREATE TABLE 新表 SELECT * FROM 旧表;
-- 完整复制表的结构、主键、索引,未曾复制数据
CREATE TABLE 新表 LIKE 旧表;
INSERT INTO 新表 SELECT * FROM 旧表; -- 数据复制

9、存储过程

SQL语句集,也可以写一些业务内容

  • 注意:

    =是判断

    :=是赋值

    =只有在set和update时才是和:=一样

  • 赋值操作时

    1. SELECT…INTO…
    2. SET param1 = param2;
    3. SELECT @param := value (OUT里面)

语法:

-- 创建
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语句

    IF 条件1 THEN 操作1;
    [ELSEIF 条件2 THEN 操作2]...
    [ELSE 操作3];
    END IF;
    
  • CASE语句

    CASE 变量
    	WHEN 值1 THEN
    	操作1;
    	[WHEN 值2 THEN 操作2]...
    	[ELSE 操作3]
    END CASE;
    
  • LOOP

    name_loop:LOOP
    	执行语句块;
    	
    	-- 出循环
    	IF 条件1 THEN
    		LEAVE name_loop;
    	END IF;
    END LOOP;
    
  • WHILE

    WHILE 条件
    	DO 执行语句块;
    END WHILE;
    
  • REPEAT

    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;
    

10、事务

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];
    
    1. 脏读:某一个事务已更新一份数据,另一个事务读取了同一份数据,由于某些原因,导致前一个事务回滚操作,后面的事务读取的数据不正确。

    2. 不可重复读:在一个事务的两次査询数据不一致,这可能是两次查询过程中,另一个事务更新原有的数据。

    3. 幻读:在一个事务中两次查询数据条数不一致,例如:在一个事务中查询了几列值,另一个事务此时插入了几条新数据,先前的事务再次查询时,就发现多了几条数据是没有的。

11、JDBC

Java连接数据库:

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();
			}
		}
	}
}

BaseDao.java

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;
	}
}
 类似资料: