精华内容
下载资源
问答
  • SQL语句入门,MySQL入门,数据库配置,SQLyog使用,JDBC入门,如何学习数据库,如何进行数据库配置,如何进行数据库远程访问

    数据库学习:https://blog.csdn.net/weixin_39778570/article/details/95066091
    Java(持续更新):https://blog.csdn.net/weixin_39778570/article/details/94667501

    下载好SQL服务,并启动,下载好SQLyog,打开SQLyog,新建一个数据库连接,打注释的填写名字,一开始不用设置密码进入

    SQL语句基本类型

    CRUD
    增加(Create)
    读取查询(Retrieve)
    更新(Update)
    删除(Delete)

    创建数据库

    CREATE DATABASE 数据库名 ;
    ##删除数据库
    DROP DATABASE 数据库名;

    切换数据库

    USE 数据库名

    创建表

    CREATE TABLE `student` (
      `id` int(11) NOT NULL,
      `name` varchar(64) NOT NULL,
      `phone` varchar(16) DEFAULT '13800000000',
      `birthday` date DEFAULT NULL,
      PRIMARY KEY (`id`)
    );
    

    删除表

    DROP TABLE命令可以删除表
    DROP TABLE `student`;
    DROP TABLE IF EXISTS `student`;
    

    修改表

    ALTER TABLE `student`
    

    ALTER TABLE user10 RENAME TO user11; -- 修改表名user10 到 user11
    ALTER TABLE test add  column name varchar(10); --添加表列  
    ALTER TABLE test drop  column name; --删除表列  
    ALTER TABLE test modify address char(10) --修改表列类型  
    ALTER TABLE test change address address  char(40)  
    ALTER TABLE test change column address address1 varchar(30)--修改表列名
    

    对表的增删改查

    select * from xxx;
    insert into xxx values();
    update xxx set xx=xx where xxx=xxx and xxx=xxx;
    delete from xxx where xx=xxx and xxx=xxx or……;
    

    查询:

    简单查询

    select * from tablename;//查询全部
    select name as '姓名' from student;
    

    通配符%

    select 字段名 from 表名;
    

    模糊匹配

    where  name LIKE '%良%'
    where  name LIKE '张%'
    where  name LIKE '张%良'
    

    使用函数

    SELECT * FROM student 
    WHERE  YEAR(birthday)>=1980 
           AND YEAR(birthday)<1990  ;
    

    增添:

    INSERT INTO 表名
    ( 列1, 列2, …, 列N)
    VALUES
    ( 值1, 值2, …, 值N)
    示例:

    INSERT INTO `af_school`.`student` 
    	(`id`, `name`, `phone`, `birthday`) 
    VALUES
    	('20180008', '小王', '13410012908', '1993-9-10'),
    	('20180009', '小1', '13410012908', '1993-9-10'),
    	('20180010, '小王', '13410012908', '1993-9-10'),
    	('20180011, '小王', '13410012908', '1993-9-10');
    

    数据名、表名、列名都加反引号
    值都加单引号
    列名和值一一对应
    简化写法
    一次插入多行数据

    修改:

    update tablename set xx=xx where xx=xx;
    例1:

    updete tablename set id=1 where name="小王"; # 把name为小王的id更改为1
    

    例2:

    updete tablename set name='张飞' where id="20180001" and sex=1;
    # 把name为董磊或者sex=1的name改为张飞。条件用and、or连接
    

    删除:

    delete from tablename where xx=xxx;
    # 例1:
    delete from tablename;//删除表
    # 例2:
    delete from tablename where id=1;//把id为1的数据删掉
    

    like语句:

    %代表0到多个字符
    _代表一个字符

    selcet name from student where name like '张%'//查询student表中name以张开头的人的name
    selcet name from student where name like '张_'//查询student表中name以张开头的2个字的name
    

    distinct

    distinct只能返回它的目标字段,无法返回其他字段。所以我们往往用来返回不重复字段的条数
    如:(count(distinct id))

    # 用法2: 
    select distinct name from user;#查询所有的姓名(重复的只显示一次)
    # 用法3: 
    select distinct name,id from user;#查询出所有的姓名与id(只有同时重复的才只显示一次)
    # 用法4:
    select name,distinct id from user;#distinct只能放在要查询字段的开头
    

    group by

    select name from user group by name;
    select sex,COUNT(*) from user GROUP BY sex having +条件;//group by后面写条件用having
    

    判断一个值是否为null用 is null is not null

    关系运算符 大于> 小于< 不等于!=、<>

    order by

    ASC表示升序 ( ascending )
    DESC表示降序 ( descending )
    select *
    from emp
    ORDER BY deptno,sal//先根据deptno排再根据sal排,默认升序(ASC)降序用DESC
    select *
    from emp
    ORDER BY deptno DESC,sal DESC//都降序排,第一个DESC不能省略,否则第一个为升序

    常用基本函数:

    1.lower():把字段转换为小写
    2.upper():吧字段转换为大写
    3.concat(str1,str2,……):将多个字符串连接成一个字符串
    3.5.concat_ws(separator,str1,str2,……):将多个字符串连接成一个字符串,中间用separator隔开
    4.substr(String str,num start,num length):等同于substring(),mid()从start位置开始取length长度的字符串
    PS:第一个字符的位置是1不是0
    5.length(str):得到字符串的长度
    6.round(num,num):四舍五入函数,第一个参数为小数,第二个为以几位小数来四舍五入
    如:ROUND(2.545,2)结果为2.55,ROUND(2.545,1)为2.5

    分组函数:

    avg(字段):计算出查询结果中该字段的平均值
    max(字段):计算出查询结果中该字段的最大值
    min(字段):计算出查询结果中该字段的最小值
    sum(字段):计算出查询结果中该字段的值的和
    count(字段):计算出查询结果中该字段的个数

    子查询:也叫内部查询,如select avg(score) from studentscore就是子查询

    例:select name,score form studentscore where score>(select avg(score) from studentscore) order by score DESC
    查询学生成绩表里分数低于平均成绩的学生姓名和成绩,并根据分数降序排列

    一个博客:
    http://blog.51cto.com/9291927/2087947

    数据库设计

    表的设计

    数据库名: 全小写,用下划线连接
    推荐为 company_project
    表名: 全小写,用下划线连接
    例如 user_role student_exam
    列名 :第一个单词小写,后面首字母大写
    displayName ,numView
    当一个表经常被访问时,要精心设计
    合适的数据类型
    比如,对于整型来说有tinyint smallint int bigint
    tinyint 比 int 可能有哪些好处?
    节省存储空间 (如果表的规模很小,则忽略)
    加快传输效率 (如果MySQL同机部署,则忽略)
    加快数据备份的速度 (如果数据备份不常发生,则忽略)

    主键: Primary Key

    主键的作用:快速定位,保证唯一性

    设计时要注意两点:
    1 每一个表都应设立主键
    2 主键字段一般用整数或短字符串
    ##索引 Index
    学号 姓名 性别 生日 手机号
    1 … 1990-10-18 …
    2 … 1980-12-10 …
    3 … 1982-4-19 …
    4 … 1982-8-10 …
    5 … 1983-1-26 …
    比如说,student表用于表示学生信息
    要查找1982年出生的 …只能从前往后遍历 …
    为了加快按日期查询的速度,可以建立生日的索引
    主键和索引原理:
    https://www.cnblogs.com/aspwebchh/p/6652855.html

    连接

    内连接 INNER JOIN (做了笛卡尔积)
    外连接 (做了拼接)
    左外连接 LEFT OUTER JOIN
    右外连接 RIGHT OUTER JOIN
    全连接、交叉连接 …
    SELECT *
    FROM student a INNER JOIN exam b
    ON a.id = b.id
    on和where的区别:
    https://www.cnblogs.com/aspwebchh/p/6726181.html
    ##外键FOREIGN KEY ,是一种约束条件
    外键,作为一种约束条件,用于维护数据的完整性。(不让用户乱删、错改)
    但如果清楚数据库的结构的话,也可以不使用外键
    1、CASCADE:级联
    (1)所谓的级联删除,就是删除主键表的同时,外键表同时删除。

    2、NO ACTION(非活动,默认)、RESTRICT:约束/限制
    当取值为No Action或者Restrict时,则当在主键表中删除对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除。(即外键表约束主键表)
    3、SET NULL
    当取值为Set Null时,则当在主键表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(,一样是外键表约束主键表,不过这就要求该外键允许取null)。

    NO ACTION和RESTRICT的区别:只有在及个别的情况下会导致区别,前者是在其他约束的动作之后执行,后者具有最高的优先权执行。

    数据库设置

    1设置用户授权

    GRANT命令的语法:
    grant 
    all privileges 
    	on 库名.表名 
    	to '用户名'@'IP地址' 
    	identified by '密码' 
    	with grant option ;
    

    其中,
    all privileges 表示授予所有权限,其实可以把各项权限单列出来
    on 指定该用户可以访问的数据库/表
    to 指定用户名、和客户端IP范围
    identified by 指定密码
    后面还可以分别指定增删改查权限

    示例:

    GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' IDENTIFIED BY 'a1b2c3' WITH GRANT OPTION;
    # *.*表示所有数据库所有表
    GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY 'a1b2c3' WITH GRANT OPTION;
    
    GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY ' a1b2c3' WITH GRANT OPTION;
    
    FLUSH PRIVILEGES;   /* 运行此命令则立即生效,不需要重启服务器 */
    

    2 修改密码

    UPDATE mysql.user 
    	SET `password`=PASSWORD('a1b2c3') 
    	WHERE `Host`='127.0.0.1' AND `User`='root'
    

    其中,PASSWORD是一个MySQL的函数,用于把字符串加密成密码字符串

    3 允许 root远程访问

    运行以下两行,即允许客户端从任意IP来访问服务器

    GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'a1b2c3' WITH GRANT OPTION;
    FLUSH PRIVILEGES;  
    

    其中,‘root’@’%’ 是设置这两个字段: Host=’%’ User=‘root’ ,这表示所有ip地址都能访问到

    其实也设置为一个子网范围,如 ‘root’@‘192.168.8.%’ 则允许root从IP地址为 192.168.8.%的子网来访问。

    4 立即生效

    所有的用户、密码、授权操作不会立即生效,而是在重启MySQL服务器后才会生效。

    如果想立即生效,则运行

    FLUSH PRIVILEGES;  
    

    MySQL连接数:指客户端发起的网络连接的数量

    查看最大连接数 (my.ini中设置)

    SHOW VARIABLES LIKE 'max_connections'
    

    查看当前连接

    SHOW STATUS LIKE 'Threads%'        /* 连接数量 */
    SHOW processlist                                    /* 连接详情 */
    SHOW full processlist
    

    jdbc

    连接数据库

    需要ip、端口(mysql默认3306),数据库名,用户名,密码
    构造url链接

    String urlfmt = "jdbc:mysql://%s:%d/%s?useUnicode=true&characterEncoding=UTF-8";
    String connectionUrl = String.format(urlfmt, ip, port, catalog); // ip、端口、数据库名
    Connection conn = DriverManager.getConnection(connectionUrl, username, password);
    

    数据库查询

    // 数据库查询, Statement语句 ResultSet结果集

    
    String username= "root";
    String password = "a1b2c3";
    String connectionUrl = "jdbc:mysql://127.0.0.1:3306/cp_school?useUnicode=true&characterEncoding=UTF-8";
    
    Connection conn = DriverManager.getConnection(connectionUrl, username, password);
    System.out.println("连接成功!");
    		
    ///
    Statement stmt = conn.createStatement(); 
    ResultSet rs = stmt.executeQuery("SELECT * FROM student");
    
    //如果有数据,rs.next()返回true
    while(rs.next())
     {
      	// 取出这一行记录
      	int id = rs.getInt("id");
      	String name = rs.getString("name");
      	String phone = rs.getString("phone"); // 可能为null
      	Date birthday = rs.getDate("birthday");
      	
      	System.out.println(id + "\t" + name + "\t" + phone + "\t" + birthday);	           
     }
    
     // 显示元数据信息
    ResultSetMetaData rsmd = rs.getMetaData();
    int numColumns = rsmd.getColumnCount();
    for(int i=1; i<=numColumns; i++) // 列序号 1,2,3, ...
    {
    	String name = rsmd.getColumnName(i); // 原始列名
    	String label = rsmd.getColumnLabel(i); // 别名
    	int type = rsmd.getColumnType(i); // 类型, 参考 java.sql.Types定义
    	String typeName = rsmd.getColumnTypeName(i); // 类型名称
    	
    	System.out.printf("第%d列: %s, %s, %s \n", i, name, label, typeName);
    }
    //
    conn.close();
    System.out.println("关闭连接!");
    

    连接成功!
    20180111 小哈 1992-10-02
    20180402 小q 1992-10-02
    20180404 小哈 1992-10-02
    20180411 小q 1992-10-02
    第1列: id, 学号, INT
    第2列: name, 姓名, VARCHAR
    第3列: birthday, birthday, DATE
    关闭连接!

    // 自增处理:执行sql语句并取回自增id
    stmt.execute(sql, Statement.RETURN_GENERATED_KEYS);
    
    // 获取自增字段的结果集
    ResultSet keys = stmt.getGeneratedKeys();
    
    // 取回自增id
    String id = keys.getString(1);
    

    c3p0连接池

    首先配置xml

    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
    
        <default-config>
            <property name="driverClass">com.mysql.jdbc.Driver</property>     
            <property name="jdbcUrl">jdbc:mysql://127.0.0.1/cp_school</property>     <!--  ip和数据库名 -->
            <property name="user">root</property>                                    <!--  用户名      -->
            <property name="password">a1b2c3</property>                              <!--  密码        -->
    
    	    <property name="initialPoolSize">5</property>
    	    <property name="minPoolSize">2</property>
    	    <property name="maxPoolSize">10</property>
    	    <property name="maxIdleTime">30</property>
        </default-config>
    
    </c3p0-config>
    
    // 全局对象
    	static ComboPooledDataSource cpds = new ComboPooledDataSource(); // 连接池一般不关闭
    	
    	public void testQuery() throws Exception
    	{		
    		// 一个Connection代表一次访问
    		Connection conn = cpds.getConnection();
    		
    		// 查询操作		
    		Statement stmt = conn.createStatement(); 
    		ResultSet rs = stmt.executeQuery("SELECT * FROM student");		
    	    while(rs.next())
    	    {
    	    	// 取出这一行记录
    	    	int id = rs.getInt("id");
    	    	String name = rs.getString("name");
    	    	String phone = rs.getString("phone"); // 可能为null
    	    	Date birthday = rs.getDate("birthday");
    	    	System.out.println(id + "\t" + name + "\t" + phone );	           
    	    }    
    		
    		conn.close();// 连接放回池子
    
    	}
    
    展开全文
  • 实验九 JDBC数据库访问二 一、实验目标: 掌握并熟练使用JDBC查询数据库 区分精确查询与模糊查询,掌握预处理语句。 二、实验内容: 在实验八的基础上完成 (必做)完成全部查询和条件查询 用MVC模式完成查询全部...

    实验九 JDBC数据库访问二

    一、实验目标:

    掌握并熟练使用JDBC查询数据库
    区分精确查询与模糊查询,掌握预处理语句。

    二、实验内容:

    在实验八的基础上完成
    (必做)完成全部查询和条件查询
    用MVC模式完成查询全部记录及按关键字商品号查询(精确查询)。
    (选作):按商品名模糊查询,按某个排序查询或者输入行号,定位某条记录等。。。
    JavaBean的设计要求:
    Message.java:数据类,与表相对应的数据模型
    MessageDAO.java:业务类,所有和表相关的操作如查询、添加、删除、修改等操作都封装在此类中。

    三、注意事项

    ⒈认真填写实验报告
    ⒉遵守实验室各项制度,服从实验指导教师的安排
    ⒊按规定的时间完成实验

    实验十 JDBC数据库访问三

    一、实验目标:

    掌握并熟练使用JDBC操作数据库:添加,删除及修改。
    练习使用数据库连接池及其他相关技术。

    二、实验内容:

    1. 在添加记录的基础上,实现对表记录的更新、删除;
      a) 用MVC模式来完成
      b) 要考虑操作过程中的数据安全性问题,比如添加、更新记录要检查用户名,删除如果是基于编号的删除要考虑编号是否存在
    2. (选做)尝试用数据连接池来完成数据库的连接。
    3. 用DAO设计模式对程序进行重构。

    三、注意事项

    ⒈认真填写实验报告
    ⒉遵守实验室各项制度,服从实验指导教师的安排
    ⒊按规定的时间完成实验

    项目代码:

    package cn.jdbc.domain;
    
    public class Student 
    {
    	
    	private String sno; // 学号
    	
    	private String sname; // 姓名
    	
    	private int sage; // 年龄
    	
    	public String getSno() 
    	{
    		return sno;
    	}
    	public void setSno(String sno) 
    	{
    		this.sno = sno;
    	}
    	public String getSname() 
    	{
    		return sname;
    	}
    	public void setSname(String sname) 
    	{
    		this.sname = sname;
    	}
    	public int getSage() 
    	{
    		return sage;
    	}
    	public void setSage(int sage) 
    	{
    		this.sage = sage;
    	}
    
    }
    
    
    package cn.jdbc.dao;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.ArrayList;
    import java.util.List;
    
    
    import cn.jdbc.domain.Student;
    import cn.jdbc.utils.Utils;
    
    /*
     * 完成对数据库的增删改查操作
     */
    public class StudentDao {
     //为学生表添加数据
        public boolean insert(Student student) {
            Connection conn = null;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            try {
                // 获得数据的连接
                conn = Utils.getConnection();
                // SQL语句
                String sql="insert into student values(?,?,?)";
                //得到预编译对象
                stmt=conn.prepareStatement(sql);
                stmt.setString(1, student.getSno());
                stmt.setString(2, student.getSname());
                stmt.setInt(3, student.getSage());
                int num = stmt.executeUpdate();
                if (num > 0) {
                    return true;
                }
                return false;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                Utils.release(rs, stmt, conn);
            }
            return false;
        }
     //查询所有数据
        public List < Student > findAll() {
            Connection conn = null;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            List < Student > list = new ArrayList < Student > ();
            try {
                // 获得数据的连接
                conn = Utils.getConnection();
                // SQL语句
                String sql="select * from student";
                //得到预编译对象
                stmt=conn.prepareStatement(sql);
                rs = stmt.executeQuery();
                // 处理结果集,遍历rs结果集
                while (rs.next()) {
                    Student student = new Student();
                    student.setSno(rs.getString("sno"));
                    student.setSname(rs.getString("sname"));
                    student.setSage(rs.getInt("sage"));
                    list.add(student);
                }
                return list;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                Utils.release(rs, stmt, conn);
            }
            return null;
        }
     // 根据id查找指定的student
        public Student find(String id) {
            Connection conn = null;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            Student student = new Student();
            try {
                // 获得数据的连接
                conn = Utils.getConnection();
                //SQL语句
                String sql = "select * from student where sno=?";
                //得到预编译对象
                stmt=conn.prepareStatement(sql);
                stmt.setString(1, id);
                rs = stmt.executeQuery();
                // 处理结果集
                while (rs.next()) {                
                    student.setSno(rs.getString("sno"));
                    student.setSname(rs.getString("sname"));
                    student.setSage(rs.getInt("sage"));
                    return student;
                }
                return null;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                Utils.release(rs, stmt, conn);
            }
            return null;
        }
     //删除学生数据
        public boolean delete(String id){
          Connection conn = null;
          PreparedStatement stmt = null;
          ResultSet rs = null;
          try {
              // 获得数据的连接
              conn = Utils.getConnection();
              //sql语句          
              String sql = "delete from student where sno=?";
              //获取预处理对象        
              stmt= conn.prepareStatement(sql);
              stmt.setString(1, id);
              int num = stmt.executeUpdate();
              if (num > 0) {
                  return true;
              }
              return false;
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              Utils.release(rs, stmt, conn);
          }
          return false;
        }
     // 修改用户
        public boolean update(Student student) {
            Connection con = null;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            try {
                //获得数据的连接
                con = Utils.getConnection();
                //sql语句
                String sql="update student set sname=?,sage=? where sno =?";
                //得到预编译对象
                stmt=con.prepareStatement(sql);
                stmt.setString(1, student.getSname());
                stmt.setInt(2, student.getSage());
                stmt.setString(3, student.getSno());
                int num = stmt.executeUpdate();
                if (num > 0) {
                    return true;
                }
                return false;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                Utils.release(rs, stmt, con);
            }
            return false;
        }
    }
    
    
    package cn.jdbc.servlet;
    
    import java.io.IOException;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import cn.jdbc.dao.StudentDao;
    import cn.jdbc.domain.Student;
    
    
    public class Display extends HttpServlet {
    
    	/**
    	 * Constructor of the object.
    	 */
    	public Display() {
    		super();
    	}
    
    	/**
    	 * Destruction of the servlet. <br>
    	 */
    	public void destroy() {
    		super.destroy(); // Just puts "destroy" string in log
    		// Put your code here
    	}
    
    	/**
    	 * The doGet method of the servlet. <br>
    	 *
    	 * This method is called when a form has its tag value method equals to get.
    	 * 
    	 * @param request the request send by the client to the server
    	 * @param response the response send by the server to the client
    	 * @throws ServletException if an error occurred
    	 * @throws IOException if an error occurred
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    	{
    		request.setCharacterEncoding("UTF-8");
    		
    		//获取数据库操作的对象
    		StudentDao dao = new StudentDao();
    		//获取数组对象
    		List<Student> list = new ArrayList<Student>();
    		
    		//获取查询的学号
    		String search_sno = request.getParameter("search_no");
    		
    		//获取添加的数据
    		String add_sno = request.getParameter("add_sno");
    		String add_sname = request.getParameter("add_sname");
    		String add_sage = request.getParameter("add_sage");
    		
    		//获取修改的数据
    		String cg_sno = request.getParameter("cg_sno");
    		String cg_sname = request.getParameter("cg_sname");
    		String cg_sage = request.getParameter("cg_sage");
    		
    		//获取删除的学号
    		String del_sno = request.getParameter("del_sno");
    		
    		//查询数据
    		if(search_sno!=null){
    			Student student= dao.find(search_sno);	
    			list.add(student);
    			search_sno="";
    		}else{//显示所有的数据
    			list=dao.findAll();
    		}
    		//添加数据
    		if(add_sage!=null){
    			Student student = new Student();
    			student.setSno(add_sno);
    			student.setSname(add_sname);
    			student.setSage(Integer.parseInt(add_sage));
    			dao.insert(student);
    			list=dao.findAll();
    			add_sno="";
    			add_sname="";
    			add_sage="";
    		}
    		//修改数据
    		if(cg_sage!=null){
    			Student student = new Student();
    			student.setSno(cg_sno);
    			student.setSname(cg_sname);
    			student.setSage(Integer.parseInt(cg_sage));
    			dao.update(student);
    			list=dao.findAll();
    			cg_sno="";
    			cg_sname="";
    			cg_sage="";
    		}
    		//删除数据
    		if(del_sno!=null){
    			dao.delete(del_sno);
    			list=dao.findAll();
    			del_sno="";
    		}
    		//传递数组到jsp页面		
    		request.setAttribute("list", list);
    		request.getRequestDispatcher("index.jsp").forward(request, response);
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	
    
    	
    
    	/**
    	 * The doPost method of the servlet. <br>
    	 *
    	 * This method is called when a form has its tag value method equals to post.
    	 * 
    	 * @param request the request send by the client to the server
    	 * @param response the response send by the server to the client
    	 * @throws ServletException if an error occurred
    	 * @throws IOException if an error occurred
    	 */
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
          {
    	// TODO Auto-generated method stub
    	doGet(request, response);
    }
    
    	/**
    	 * Initialization of the servlet. <br>
    	 *
    	 * @throws ServletException if an error occurs
    	 */
    	public void init() throws ServletException {
    		// Put your code here
    	}
    
    }
    
    
    package cn.jdbc.utils;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class Utils {
    // 加载驱动,并建立数据库连接
    	public static Connection getConnection() throws SQLException,
    				ClassNotFoundException {
    //		         加载驱动
    			Class.forName("com.mysql.cj.jdbc.Driver");
    //			获取数据库连接
    			String url = "jdbc:mysql://localhost:3306/javaweb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8";
    //			用户名
    			String username = "root";
    //			密码
    	    	String password = "1234";
    			Connection conn = DriverManager.getConnection(url, username, 
    					password);
    			return conn;
    		}
    	// 关闭数据库连接,释放资源
    	public static void release(ResultSet rs, Statement stmt, Connection conn) {
    		if (rs != null) {
    			try {
    				rs.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    			rs = null;
    		}
    		if (stmt != null) {
    			try {
    				stmt.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    			stmt = null;
    		}
    		if (conn != null) {
    			try {
    				conn.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    			conn = null;
    		}
    		
    	}
    }
    
    
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
    <%@ page import="java.io.*,java.util.*,java.sql.*"%>
    <%@ page import="javax.servlet.http.*,javax.servlet.*" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML>
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <style type="text/css">
        body
        {
    	text-align: center;
        }
        </style>
        
        <title>学生数据</title>
        
        <meta charset="UTF-8">
    	<meta http-equiv="pragma" content="no-cache">
    	<meta http-equiv="cache-control" content="no-cache">
    	<meta http-equiv="expires" content="0">    
    	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    	<meta http-equiv="description" content="This is my page">
    	<!--
    	<link rel="stylesheet" type="text/css" href="styles.css">
    	-->
    
      </head>
      
      <body>
     <h2>学生信息查询系统</h2>
    
        <table align="center" border="1" cellpadding="0" cellspacing="0" width="60%">
            <thead>
                <tr>
                    <th>学号</th>
                    <th>姓名</th>
                    <th>年龄</th>
                </tr>
            </thead>
            <tbody>
            	 <c:forEach items="${list}" var="i">
                <tr >
                   	<td>${i.sno}</td>
                   	<td>${i.sname}</td>
                   	<td>${i.sage}</td>
                </tr>
                </c:forEach> 
            </tbody>
        </table>
        
        <br><br><br>
        <table align="center" border="0" cellpadding="0" cellspacing="0" width="40%">
        	<tr>
        		<td><a href="display.do">首页</a></td>
        		<td><a href="inquire.jsp">查询</a></td>
        		<td><a href="add.jsp">添加</a></td>
        		<td><a href="amend.jsp">修改</a></td>
        		<td><a href="delete.jsp">删除</a></td>
        	</tr>
        </table>
    
    </body>
    </html>
    
    
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
    <%@ page import="java.io.*,java.util.*,java.sql.*"%>
    <%@ page import="javax.servlet.http.*,javax.servlet.*" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML>
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <style type="text/css">
        body
        {
    	text-align: center;
        }
        </style>
        
        <title>修改功能</title>
        
        <meta charset="UTF-8">
    	<meta http-equiv="pragma" content="no-cache">
    	<meta http-equiv="cache-control" content="no-cache">
    	<meta http-equiv="expires" content="0">    
    	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    	<meta http-equiv="description" content="This is my page">
    	<!--
    	<link rel="stylesheet" type="text/css" href="styles.css">
    	-->
    
      </head>
    <body align="center">
        <h3>修改数据</h3>
        <form action="display.do" method="post">
            <label>学号:</label>
            <input type="text" name="cg_sno"><br><br>
            <label>姓名:</label>
            <input type="text" name="cg_sname"><br><br>
            <label>年龄:</label>
            <input type="text" name="cg_sage">
            <br><br>                
            <input type="submit" value="修改"><br><br>     
            <a href="display.do">返回首页</a><br>  
        </form>
    </body>
    </html>
    
    
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
    <%@ page import="java.io.*,java.util.*,java.sql.*"%>
    <%@ page import="javax.servlet.http.*,javax.servlet.*" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML>
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <style type="text/css">
        body
        {
    	text-align: center;
        }
        </style>
        
        <title>查询功能</title>
        
        <meta charset="UTF-8">
    	<meta http-equiv="pragma" content="no-cache">
    	<meta http-equiv="cache-control" content="no-cache">
    	<meta http-equiv="expires" content="0">    
    	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    	<meta http-equiv="description" content="This is my page">
    	<!--
    	<link rel="stylesheet" type="text/css" href="styles.css">
    	-->
    
      </head>
    <body align="center">
    	<h3>删除数据</h3>
        <form action="display.do" method="post">
            <label>删除数据学生的学号:</label>
            <input type="text" name="del_sno">
            <br><br>
            <input type="submit" value="删除"><br><br>    
            <a href="display.do">返回首页</a><br>    
        </form>
    </body>
    </html>
    
    
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
    <%@ page import="java.io.*,java.util.*,java.sql.*"%>
    <%@ page import="javax.servlet.http.*,javax.servlet.*" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML>
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <style type="text/css">
        body
        {
    	text-align: center;
        }
        </style>
        
        <title>增加功能</title>
        
        <meta charset="UTF-8">
    	<meta http-equiv="pragma" content="no-cache">
    	<meta http-equiv="cache-control" content="no-cache">
    	<meta http-equiv="expires" content="0">    
    	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    	<meta http-equiv="description" content="This is my page">
    	<!--
    	<link rel="stylesheet" type="text/css" href="styles.css">
    	-->
    
      </head>
    <body align="center">
    	<h3>添加数据</h3>
        <form action="display.do" method="post">
            <label>学号:</label>
            <input type="text" name="add_sno"> <br><br>
            <label>姓名:</label>
            <input type="text" name="add_sname"> <br><br>
            <label>年龄:</label>
            <input type="text" name="add_sage"> 
            <br><br>               
            <input type="submit" value="添加"><br><br>
            <a href="display.do">返回首页</a><br>       
        </form>
    </body>
    </html>
    
    
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
    <%@ page import="java.io.*,java.util.*,java.sql.*"%>
    <%@ page import="javax.servlet.http.*,javax.servlet.*" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML>
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <style type="text/css">
        body
        {
    	text-align: center;
        }
        </style>
        
        <title>查询功能</title>
        
        <meta charset="UTF-8">
    	<meta http-equiv="pragma" content="no-cache">
    	<meta http-equiv="cache-control" content="no-cache">
    	<meta http-equiv="expires" content="0">    
    	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    	<meta http-equiv="description" content="This is my page">
    	<!--
    	<link rel="stylesheet" type="text/css" href="styles.css">
    	-->
    
      </head>
    <body align="center">
    	 <h3>查询数据</h3>
        <form action="display.do" method="post">
            <label>查询的学号:</label>
            <input type="text" name="search_no">
            <br><br>
            <input type="submit" value="查询"> 
            <br><br>
            <a href="display.do">返回首页</a><br>      
        </form>
    </body>
    </html>
    
    
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="3.0" 
    	xmlns="http://java.sun.com/xml/ns/javaee" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
      <display-name></display-name>
      <servlet>
        <description>This is the description of my J2EE component</description>
        <display-name>This is the display name of my J2EE component</display-name>
        <servlet-name>Display</servlet-name>
        <servlet-class>cn.jdbc.servlet.Display</servlet-class>
      </servlet>
    
      <servlet-mapping>
        <servlet-name>Display</servlet-name>
        <url-pattern>/display.do</url-pattern>
      </servlet-mapping>	
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
    </web-app>
    
    

    代码说明

    由于该学习数据上传至CSDN时,数据库已经被我之前误删了,如果需要运行拷贝至具体项目,需自行组建数据库表,另外该项目依赖eclipse开发平台,需要读者自行添加驱动与各类标签库。

    项目运行结果展示

    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

    展开全文
  • JDBC本质:官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口,shi连接数据库的桥梁。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar...

    BC

    1. 概念:Java DataBase Connectivity Java 数据库连接, Java语言操作数据库

    JDBC本质:官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口,shi连接数据库的桥梁。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

    jdbcAPI:与数据库建立连接、执行SQL 语句、处理结果

    DriverManager :依据数据库的不同,管理JDBC驱动
    Connection :负责【连接数据库并担任传送】数据的任务
    Statement :由 Connection 产生、【负责执行SQL】语句
    ResultSet:负责【保存Statement执行后所产生的查询结果】

    1-1使用纯Java方式连接数据库

    由JDBC驱动直接访问数据库
    优点:完全Java代码,快速、跨平台
    缺点:访问不同的数据库需要下载专用的JDBC驱动

    1-2使用JDBC-ODBC桥方式连接数据库

    将对JDBC API的调用,转换为对另一组数据库连接API的调用
    优点:可以访问所有ODBC可以访问的数据库
    缺点:执行效率低、功能不够强大

    jdbc:mysql:///kgc?serverTimezone=UTC&useSSL=true&useUnicode=true&characterEncoding=utf-8

    MySQL 8.0 以上修改时区域 两种方式以及中文编码

    【驱动必须加cj】

    推荐:Class.forName(“com.mysql.cj.jdbc.Driver”);

    不推荐DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());

    【安全套接字协议ssl】

    url 中添加useSSL=true

    Jdbc程序中的DriverManager用于加载驱动,并创建与数据库的链接,这个API的常用方法:
        
    DriverManager.registerDriver(new Driver()) DriverManager.getConnection(url, user, password)
    注意:在实际开发中并不推荐采用registerDriver方法注册驱动。原因有二:
    1. 查看Driver的源代码可以看到,如果采用此种方式,会导致驱动程序注册两次,也就是在内存中会有两个Driver对象【一次是加载驱动,一次是获得连接】。
    2. 程序依赖mysql的api,脱离mysql的jar包,程序将无法编译,将来程序切换底层数据库将会非常麻
    烦。
    推荐方式:Class.forName("com.mysql.cj.jdbc.Driver");
    采用此种方式不会导致驱动对象在【内存中重复出现】,并且采用此种方式,程序仅仅只需要一个字符串,
    不需要依赖【具体的驱动】,使程序的【灵活性更高】
    

    1. 在客户端中修改时区

    set global time_zone = ‘+8:00’;
    set time_zone = ‘+8:00’;
    show variables like ‘%time_zone%’;

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DofrZuXg-1604303154959)(JDBC/image-20201023192142434.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UYa55F1A-1604303154961)(C:UsersASUSAppDataRoamingTyporatypora-user-imagesimage-20201020152224124.png)]

    2.每次连接数据库时的url中在库名后添加

    ?serverTimezone=UTC

    防止中文乱码:

    ?useUnicode=true&characterEncoding=utf-8

    con=DriverManager.getConnection(“jdbc:mysql://localhost:3306/kgc?serverTimezone=UTC”, “root”, “123456”);

    2.详解各个对象:

    2-1. DriverManager:驱动管理对象

    功能:驱动管理使用前需要先进行导包注意:

    mysql5之后的驱动jar包可以省略注册驱动的步骤。

    导入驱动jar包 mysql-connector-java-5.1.37-bin.jar或者mysql-connector-java-8.0.20.jar【1.复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下2.右键–>【idea 用Add As Library】【ecliise用build path放入到【在src包下建一个lib包】中】

    1-1 注册驱动:告诉程序该使用哪一个数据库驱动jar

    可以添加不同数据库的驱动【需要下载对应的架包】

    static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。

    //DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());不推荐使用

    这种方式来加载驱动

    写代码使用: Class.forName(“com.mysql.jdbc.Driver”);

    通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块

    static {

    try {

    ​ java.sql.DriverManager.registerDriver(new Driver());

    } catch (SQLException E) {

    ​ throw new RuntimeException(“Can’t register driver!”);

    }

    }

    2-1-1.0 常见数据库写法以及Url祥解

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kp5FYlxe-1604303154963)(JDBC/image-20201022075412981.png)]

    注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。

    2-2. 获取数据库连接con:

    方法1:【三个参数分开写】

    static Connection getConnection(String url, String user, String password)

    方法2:【三个参数写在一起】

    static Connection getConnection("jdbc:/mysql:///kgc&useSSL=true? user=root&password=123456”)

    参数:

    url:指定连接的路径

    语法:jdbc:mysql://ip地址(域名):端口号/数据库名称

    例子:jdbc:mysql://localhost:3306/db3

    细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称

    user:用户名

    password:密码

    1. Connection:数据库连接对象

    2. 功能:

    3. 获取执行sql 的对象

    2. 管理事务:

    开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务

    提交事务:commit()

    回滚事务:rollback()

    2-3Statement:执行sql的对象[【编译与预编译】

    Jdbc程序中的Statement对象用于【向数据库发送SQL语句】,
     Statement对象常用方法: 【如果是preparedstatement不加参数sql】
    executeQuery(String sql) :用于向数据发送查询语句。 
    executeUpdate(String sql):用于向数据库发送insert、update或delete语句 
    execute(String sql):用于向数据库发送任意sql语句 
    addBatch(String sql) :把多条sql语句放到一个批处理中。 
    executeBatch():向数据库发送一批sql语句执行。
    
    

    Statement createStatement()

    PreparedStatement prepareStatement(String sql)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G11kZbSG-1604303154964)(JDBC/image-20201021113028668.png)]

    2-4执行SQL语句返回结果集或者行数;

    执行sql

    2-3-1boolean execute(String sql) :可以执行任意的sql 了解

    1. -3-2int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
    返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。

    2-3-3 ResultSet executeQuery(String sql) :执行DQL(select)语句

     account表 添加一条记录
    
    
    ​     int count = stmt.executeUpdate(sql);//影响的行数
    
    ​     System.out.println(count);
    
    ​     if(count > 0){
    
    ​       System.out.println("添加成功!");
    
    ​     }else{
    
    ​       System.out.println("添加失败!");
    
    ​     }
    

    2-4-1ResultSet:结果集对象,封装查询结果

    boolean next(): 【游标】向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true

    默认游标指向第一行结果之前

    getXxx(参数):获取数据

    Xxx:代表数据类型 如: int getInt() , String getString()

    while(it.next()){

    //根据获取【列】的数据类型或者是字段下标,分别调用rs的相应方法【映射到java对象】中

    syso(rs.getInt(1)+“\t学员名字”+rs.getString(student_name));

    }

    可以用getString()接收任何数据类型

    【增删改时,在预编译后,通过预编译对象可以用setString()给任何下标进行赋值】

    参数:

    1. int:代表列的编号,从1开始 如: getString(1)

    2. String:代表列名称。 如: getDouble(“balance”)

    使用步骤:

    1. 游标向下移动一行

    2. 判断是否有数据

    3. 获取数据

    //循环判断游标是否是最后一行末尾。

    ResultSet【用来接收stm预编译对象执行SQL语句的结果】
    既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法: 
    获取任意类型的数据 
    getObject(int index) 
    getObject(string columnName) 
    获取指定类型的数据,例如: 
    getString(int index) //根据下标获取对象的值
    getString(String columnName) //根据字段名(列)获取对象的值
    ResultSet还提供了对结果集进行滚动的方法: 
    next():移动到下一行 
    Previous():移动到前一行 
    absolute(int row):移动到指定行 
    beforeFirst():移动resultSet的最前面。 
    afterLast() :移动到resultSet的最后面
    

    2-4-2结果集获得当前日期【插入或更改时的日期】进行日期赋值

    preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第五个占位符? 的值赋值为new Date(new java.util.Date().getTime());//插入当前时间

    也可以手动输入stm.setString(“ 2020-10-20 12-00-00”);

     select UTC_TIMESTAMP() 获取世界标准是时间
    
    select EXTRACT(HOUR FROM TIMEDIFF(NOW() ,UTC_TIMESTAMP()))  数据库时间与标准时间 相差的时间
    
    DATE_FORMAT()函数
         
     将时间戳转换为日期格式:比如降14555042682016-02-15 10:44:28
    
    1 select device.register_time a,FROM_UNIXTIME(device.register_time,'%Y-%m-%d %H:%i:%s') as registerTime from tm_data_newdevice  device
    
    
    

    2-4-5可 将时间戳转换为日期格式:比如降1455504268→2016-02-15 10:44:28

    1 select device.register_time a,FROM_UNIXTIME(device.register_time,'%Y-%m-%d %H:%i:%s') as registerTime from tm_data_newdevice  device
    

    列号或列名标识列

    while ( rs.next() ) {
    	System.out.print( rs.getInt(1) +"t");
    	System.out.print( rs.getString(2) +"t");
    	System.out.print(rs.getInt("loginPassword")+ "t");
    	… …
    }
    
    
       while(rs.next()){
    
    
    ​       //获取数据
    ​       System.out.println(rs.getInt(1) + "---" + rs.getString("name") + "---" + rs.getDouble(3)+rs.getDate(4));
    
    ​     }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dXJENiEs-1604303154965)(C:UsersASUSAppDataRoamingTyporatypora-user-imagesimage-20201020191837104.png)]

    2-4-6查询【聚合函数】

    例如查询count(1)查询学生人数结果是单列,

    1.可以直接在

    while(rs.next()){

    system.out.println(rs.getInt(1));//第一列的值StringInt

    //2system.out.println(rs.getInt(“总人数”));//要么聚合函数必须起别名。

    package cn.kgc.tangcco.test1021;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.Scanner;
    
    public class TestJuheFunction {
     public static void main(String[] args) throws SQLException {
    	//声明接口和手动输入关键字;
    	 Connection con=null;
    	 ResultSet rs=null;
    	 PreparedStatement stm=null;
    	 Scanner input = new Scanner(System.in);
    	
    	try {
    	Class.forName("com.mysql.cj.jdbc.Driver");
    //	2.获得连接
         con=DriverManager.getConnection("jdbc:mysql:///kgc", "root", "123456");
    //     3.编写sql语句并预编译,执行
         String sql="select count(1) 总人数 from student";
    //     String sql="select count(1) studentNums from student";//起中英文别名都行
         stm=con.prepareStatement(sql);
         
    //     4.接收预编译对象的数据并遍历
         rs=stm.executeQuery();
         while (rs.next()) {
    
        	 System.out.println(rs.getInt("总人数"));
    //  System.out.println(rs.getInt(studentNums));  	//此时用英文做变量名 
    		
    	}
        		 
    	} catch (Exception e) {
    		e.printStackTrace();
    	}finally {
    		if (rs!=null) {
    			rs.close();
    		}
    		if (stm!=null) {
    			stm.close();
    		}
    		if (con!=null) {
    			con.close();
    		}
    	}
    }
    }
    /
     
    48
    
      /
    

    }

    2-5释放资源

    • 释放ResultSet, Statement,Connection。

    • 数据库连接(Connection)是非常稀有的资源,用完后必须马上释放,如果Connection不能及时正确的关闭将导致【系统宕机】Connection的使用原则是尽量晚创建,尽量早的释放

    • 。关闭资源

      可以关闭结果集、命令、连接

      注意:注意顺序,倒着关闭

      连接若从连接池(后面讲)获取,不需要关闭

    3.SQL注入问题与占位符?

    所谓SQL注入,

    就是通过把SQL命令插入到Web表单提交或页面请求url的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。

    【利用or或者是– 注释符号及引号。获取所有人的密码或者免验证登录;利用statement需要拼接sql语句的漏洞】在预编译的过程中添加的内容只会作为字符段的一部分,不会改变sql语句的结构;

    不要以为在输入框做个检查就够了,不要忘记了,我们web提交表单,是可以模拟url直接访问过去,绕开前段检查。因此,必须是后端,或是数据来检查才能有效防止。

    (1)检查用户输入的合法性;【输入框验证】

    (2)将用户的登录名、密码等数据加密保存。【md5加盐】

    (3)预处理SQL。【采用占位符,无论输入什么,都作为字段内容】

    (4)使用存储过程实现查询,虽然不推荐,但也是一个方法。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9pqvimka-1604303154966)(C:UsersASUSAppDataRoamingTyporatypora-user-imagesimage-20201020173808157.png)]

    MySQL预处理是怎么防止的呢?

    其实是因为SQL语句在程序运行前已经进行了预编译,在程序运行时第一次操作数据库之前,SQL语句已经被数据库分析,编译和优化,对应的执行计划也会缓存下来并允许数据库已参数化的形式进行查询,当运行时动态地把参数传给PreprareStatement时,即使参数里有敏感字符如 or '1=1’也数据库会作为【一个参数一个字段的属性值】来处理而不会作为一个SQL指令,如此,就起到了SQL注入的作用了

    1. :在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题

    2. 输入用户随便,输入密码:a’ or ‘a’ = 'a

    3. sql:select from user where username = ‘fhdsjkf’ and password = ‘a’ or ‘a’ = ‘a’

    4. 解决sql注入问题:使用PreparedStatement对象来解决

    5. 预编译的SQL:参数使用?作为占位符

    6. 步骤:

    7. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar

    8. 注册驱动

    9. 获取数据库连接对象 Connection

    10. 定义sql

    注意:sql的参数使用?作为占位符。 如:select from user where username = ? and password = ?;

    1. 获取执行sql语句的对象 PreparedStatement Connection.prepareStatement(String sql)

    6. 给?赋值:

    方法: setXxx(参数1,参数2)

    参数1:?的位置编号 从1 开始

    参数2:?的值

    1. 执行sql,接受返回结果,不需要传递sql语句

    2. 处理结果

    3. 释放资源

    4. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作

    5. 可以防止SQL注入

    6. 效率更高

    方法名说 明
    boolean next()将游标从当前位置向下移动一行
    boolean previous()游标从当前位置向上移动一行
    void close()关闭ResultSet 对象
    int getInt(int colIndex)以int形式获取结果集当前行指定列号值
    int getInt(String colLabel)以int形式获取结果集当前行指定列名值
    float getFloat(int colIndex)以float形式获取结果集当前行指定列号值
    float getFloat(String colLabel)以float形式获取结果集当前行指定列名值
    String getString(int colIndex)以String 形式获取结果集当前行指定列号值
    String getString(String colLabel)以String形式获取结果集当前行指定列名值

    4.编译[【需要while(rs.next())获得结果集】

    ResultSet executeQuery(String sql) 执行SQL查询并获取到ResultSet对象
    int executeUpdate(String sql) 可以执行插入、删除、更新等操作,返回值是执行该操作所影响的行数
    boolean execute(String sql) 可以执行任意SQL语句,然后获得一个布尔值,表示是否返回ResultSet

    更新:/,修改删除

    package cn.kgc.tyl.test1020;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    
    
    
    
    public class UpdateStatement {
       public static void main(String[] args) throws SQLException {
    	   Connection con=null;
    	Statement stm=null;
    	   
    	
    	try {
    //		1.加载驱动
    		Class.forName("com.mysql.cj.jdbc.Driver");
    
    //		2.获得连接
    	    con=DriverManager.getConnection("jdbc:mysql://localhost:3306/kgc?serverTimezone=UTC", "root", "123456");
    	    if (con!=null) {
    			System.out.println("连接成功");
    		}
    //	    3.写sql语句并编译【先写SQL语句再执行可能出现SQL注入的问题,不安全;】编译必须用编译对象接收,否则空指针异常
    	   
    	    String sql3="update student set student_name= '远哥' where student_num=3";
    	 
    //	    
    	    stm = con.createStatement(); 
    	
    	     int count=stm.executeUpdate(sql3);//返回为int类型
    	     if (count>0) {
    			System.out.println("修改成功");
    		}else { 
    			System.out.println("修改失败");
    		}
    
    	} catch (Exception e) {
    		e.printStackTrace();
    	}finally {
    	
    	
    		if (stm!=null) {
    			stm.close();
    			
    		}
    		if (con!=null) {
    			con.close();
    		}
    		
    	}
    	
    }
    }
    /更新成功/
    

    查询

    package cn.kgc.tyl.test1020;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    
    
    public class SelectStatement {
       public static void main(String[] args) throws SQLException {
    	   Connection con=null;
    	   Statement stm=null;
    	   ResultSet rs=null;
    	try {
    //		1.加载驱动
    		Class.forName("com.mysql.cj.jdbc.Driver");
    
    //		2.获得连接
    	    con=DriverManager.getConnection("jdbc:mysql://localhost:3306/kgc?serverTimezone=UTC", "root", "123456");
    	    if (con!=null) {
    			System.out.println("连接成功");
    		}
    //	    3.写sql语句并编译【先写SQL语句再执行可能出现SQL注入的问题,不安全;】
    	    String sql1="select *  from student";
    	    stm= con.createStatement();
    //	    4.用结果集接收执行的sql语句并输出
    	     rs=stm.executeQuery(sql1);
    	    while (rs.next()) {
    			System.out.println(rs.getInt("student_num")+"姓名"+rs.getString("student_name"));//com.mysql.cj.jdbc.result.ResultSetImpl@6366ebe0
    			
    		}
    	} catch (Exception e) {
    		e.printStackTrace();
    	}finally {
    		if (rs!=null) {
    			rs.close();
    		}
    		if (stm!=null) {
    			stm.close();
    			
    		}
    		if (con!=null) {
    			con.close();
    		}
    		
    	}
    }
    }
    /
     
     连接成功
    1姓名远哥
    2姓名远哥
    3姓名Lucy
    4姓名韩文
    5姓名果果
    6姓名狂龙
    7姓名赵1
    8姓名赵2
    9姓名赵3
    10姓名赵4
    11姓名赵5
    12姓名赵6
    14姓名赵14
    15姓名赵15
    20000姓名赵16
    17姓名赵17
    18姓名赵18
    19姓名赵19
    20姓名赵20
    21姓名赵21
    22姓名赵22
    24姓名赵24
    25姓名赵李
    72姓名赵李李1
    73姓名赵李1
    74姓名李赵1
    75姓名李1
    63姓名赵25
    26姓名赵26
    27姓名赵27
    28姓名赵28
    29姓名赵29
    30姓名赵30
    31姓名赵31
    32姓名赵32
    33姓名赵33
    34姓名赵34
    35姓名赵35
    36姓名赵36
    37姓名赵37
    38姓名赵38
    39姓名赵39
    48姓名赵40
    10000姓名张三
    11000姓名张非
    
      /
    

    5.预编译【获得预编译对象后,要对占位符的对象赋值】

    5-1预编译的好处:

    【提高了安全性;提高了SQL语句执行的性能;提高了代码的可读性和可维护性】

    1、预编译之后的 SQL 多数情况下可以直接执行,DBMS 不需要再次编译。

    2、越复杂的SQL,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。

    3、相同的预编译 SQL 可以重复利用。(把一个 SQL 预编译后产生的 PreparedStatement 对象缓存下来,

    下次对于同一个 SQL,可以直接使用这个缓存的 PreparedState 对象。)

    4、可以将这类SQL语句中的值用占位符替代,不需要每次编译,可以直接执行,

    只需执行的时候,直接将每次请求的不同的值设置到占位符的位置。

    5、预编译可以视为将sql语句模板化或者说参数化。

    5-2.相似功能的代码抽取封装成方法,减少代码冗余

    因为不同的数据库会有不同的实现,对数据库的操作一般抽取成接口,在以后的开发中可以降低耦合

    5-3.Statement与PreparedStatement区别

    【stm主要好处安全,防止非法sQL注入;编译一次,可返回执行多次,效率高】

    1.Statement由方法createStatement()创建,该对象用于发送简单的SQL语句
    PreparedStatement由方法prepareStatement()创建,该对象用于发送带有一个或者多个输入参数的SQL语句
    SQL语句使用“?”作为数据占位符
    使用setXxx()方法设置数据
    PreparedStatement—预编译
    2.效率、性能、开销
    3.安全性
    4代码可读性

    5-4三大对象(接口)
    ① 连接
    Connection
    ② 命令
    父父接口Statement 不推荐使用
    父接口PreparedStatement 广泛使用

    5-4预编译输入日期时注意事项

    1。年月日时 String starttime=input.next();

    2.年月日时分秒时格式为Sting endTime=input.nextLine(); //中间有空格,不会换行,

    3.为日期赋值时当插入当前时间时外层new java.util.Date,内层new java.sql.Date.然后调用getTime()可以获得当前年月日【时分秒默认都是0】

    package cn.kgc.tangcco.test1021;
    
    import java.sql.Connection;
    import java.sql.Date;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.Scanner;
    
    import com.mysql.cj.util.Util;
    
    public class InsertNowTime {
     public static void main(String[] args) throws SQLException {
    	//声明接口和手动输入关键字;
    	 Connection con=null;
    	 ResultSet rs=null;
    	 PreparedStatement stm=null;
    	 	try {
    	Class.forName("com.mysql.cj.jdbc.Driver");
    //	2.获得连接
         con=DriverManager.getConnection("jdbc:mysql:///kgc", "root", "123456");
    //     3.编写sql语句并预编译,执行sql
         String sql=" insert into student (student_num,student_name,modify_date ) values (?,?,?)";
    //    
         stm=con.prepareStatement(sql);
    //     外部导入java.sql.Date.对象;里面导入java.util.Date.对象;获得当前时间;
         stm.setInt(1, 299);
         stm.setString(2, "光头强2");
         stm.setDate(3, new Date(new java.util.Date().getTime()) );//只能返回年月日
    //     4.接收预编译对象的数据并判断是否执行成功
        int i=stm.executeUpdate();
        if (i>0) {
    		System.out.println("修改成功");
    	}
        		
    	} catch (Exception e) {
    		e.printStackTrace();
    	}finally {
    		if (rs!=null) {
    			rs.close();
    		}
    		if (stm!=null) {
    			stm.close();
    		}
    		if (con!=null) {
    			con.close();
    		}
    	}
    }
    }
    /
     
    48
    
      /
    

    子接口CallableStatement 调用存储过程使用

    ③ 结果
    增删改:int的行数
    查询:表-> ResultSet接口

    【模糊查询】

    package cn.kgc.tangcco.test1021;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.Scanner;
    
    public class MoHuChaXun {
     public static void main(String[] args) throws SQLException {
    	//声明接口和手动输入关键字;
    	 Connection con=null;
    	 ResultSet rs=null;
    	 PreparedStatement stm=null;
    	 Scanner input = new Scanner(System.in);
    	System.out.println("请输入要查找的信息");
    	String student_num=input.nextLine();//声明模糊查询的变量
    	student_num="%"+student_num+"%";
    	try {
    	Class.forName("com.mysql.cj.jdbc.Driver");
    //	2.获得连接
         con=DriverManager.getConnection("jdbc:mysql:///kgc", "root", "123456");
    //     3.编写sql语句并预编译,执行
         String sql="select  from student where student_name like ?";
         stm=con.prepareStatement(sql);
         stm.setString(1, student_num);
    //     4.接收预编译对象的数据并遍历
         rs=stm.executeQuery();
         while (rs.next()) {
        	 System.out.println("学号t学生姓名t密码t性别");
        	 System.out.println(rs.getInt(1)+"t"+rs.getString(2)+"t"+rs.getString(3)+"t"+rs.getString(4));
    		
    	}
        		 
    	} catch (Exception e) {
    		e.printStackTrace();
    	}finally {
    		if (rs!=null) {
    			rs.close();
    		}
    		if (stm!=null) {
    			stm.close();
    		}
    		if (con!=null) {
    			con.close();
    		}
    	}
    }
    }
    /
     
     请输入要查找的信息
    福
    学号	学生姓名	密码	性别
    100	22	孙福祥	null
    
      /
    

    【更新】更改插入删除

    packagecn.kgc.tyl.test1020;
    
    import java.sql.Connection;
    
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class SelectPreparedStatement {
         public static void main(String[] args) throws SQLException {
        	 PreparedStatement stm=null;
        	 Connection con=null;
        	PreparedStatement stm2=null;
    		try {
    			Class.forName("com.mysql.cj.jdbc.Driver");//1.加载驱动
    			con=DriverManager.getConnection("jdbc:mysql:///kgc","root","123456");//2.建立连接
    			String sql = "insert into student (student_num,student_name)values(?,?)";//3.获得预编译对象并给预编译对象赋值
    			String sq2="delete from student where student_name=?";
                stm = con.prepareStatement(sql);
              
    			stm.setInt(1, 110);
    			stm.setString(2,"范永光");
    			stm.executeUpdate();//4.执行更新SQL语句
    			stm2=con.prepareStatement(sq2);
    			stm2.setString(1, "远哥");
    			stm2.executeUpdate();
    		} catch (Exception e) {
    			
    			e.printStackTrace();
    		}finally {
    			if (stm!=null) {
    				stm.close();
    			}
    			if (con!=null) {
    				con.close();
    				
    			}
    		}
    	}
    }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nFrdycSv-1604303154966)(JDBC/image-20201021173111564.png)]

    package cn.kgc.tyl.test1020;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class UpdatePareparedStatement {
     public static void main(String[] args) throws SQLException {
    	PreparedStatement stm=null;
    	Connection con=null;
    
    	try {
    //		1.加载驱动
    		
    		Class.forName("com.mysql.cj.jdbc.Driver");//先mysql再jdbc
    //		2.获得连接
    		con=DriverManager.getConnection("jdbc:mysql:///kgc","root","123456");//先jdbc再mysql
    //		3.进行预编译,并给预编译对象赋值;
    		String sq="update student set student_name=? where student_num=?";
    		stm=con.prepareStatement(sq);
    		stm.setString(1, "范增");
    		stm.setInt(2, 10);
    //		4.执行
    		int i=stm.executeUpdate();
    		if (i>0) {
    			System.out.println("更新成功;");
    		}
    	} catch (Exception e) {
    		e.printStackTrace();
    	}finally {
    		if (stm!=null) {
    			stm.close();
    		}
    		if (con!=null) {
    			con.close();
    		}
    		
    	}
    }
    }
    
    

    5-5【批量更新和循环更新】

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xz5d9MAw-1604303154968)(JDBC/image-20201022073142446.png)]

    5- sql 动态解析

    mybatis 在调用 connection 进行 sql 预编译之前,会对sql语句进行动态解析,动态解析主要包含如下的功能:

      • 占位符的处理
      • 动态sql的处理
      • 参数类型校验

    注: mybatis 默认情况下,将对所有的 sql 进行预编译。

    6.抽取JDBC工具类 JDBCUtils

    【封装工具】
    封装把公共的属性方法进行封装,用静态 的类只要加载,就可以执行;
    1.三个接口变量,增删改的方法;获得连接方法;释放资源方法【当关闭资源时,有多余的参数用null传递,比如查询方法三个变量
    ,通用增删改第三个变量就只需要传递为null就可以了】
    2.封装时,返回对象尽量用Integer或者Long【数据量上千万条时】。是对象,数量可以为null;
    3.可变长数组Object…objects可以代表0-多个对象;
    4.Dao包按照实体类分为多个包,【还可以细分为用户模块,订单模块】比如student,teacher然后在各个dao的子包中建立接口类和具体实现类比如
    /demo/src/cn/kgc/tangcco/test1022/dao/teacher/impl/TeacherDaoImpl.java;
    /demo/src/cn/kgc/tangcco/test1022/dao/student/impl/StudentDaoImpl.java
    5.输出语句时,先输出结果,再输出原因【登录失败,密码或用户不正确】
    6.dao层连接实体类和工具类,包的作用时安全性和分门别类,把具有不同共同的类放在不同的包中;
    7.工具类中方法尽量用trycatch包裹声明异常,否则在在工具类中thorows抛出异常就必须在daoimpl中声明处理异常;那么daoimpl中格式不美观

    进行JDBC封装原因:

    采用面向接口编程,可以降低代码间的耦合性
    具体有三个好处
    1.增加可读性;
    2.利于代码复用
    3.利于后期修改和维护:简化书写

    DAO模式优势:隔离了数据访问代码和业务逻辑代码;隔离了不同数据库实现

    6-2DAO模式

    面向接口编程:只关心类实现的功能,不关心具体实现过程,【实现数据无损替换】

    持久化数据存储在dao层,DB【用户请求到右边,DB端dao层返回数据到界面】

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W81zUzSA-1604303154968)(JDBC/image-20201022135451856.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ublkuO6h-1604303154969)(JDBC/image-20201020215752147.png)]

    实现类实现接口并数据库工具类,此种封装JDBC的结构即为DAO模式
    Data Access Object(数据存取对象) 位于业务逻辑和持久化数据之间实现对持久化数据的访问DAO起着转换器的作用,把实体类转换为数据库中的记录

    为解决业务代码和数据访问代码的紧耦合给修改和维护代码带来的不便,推荐使用DAO模式封装JDBC

    6-3配置文件:

    让用户脱离程序本身修改相关的变量设置——使用配置文件
    Java中的配置文件常为properties文件
    后缀为.properties
    格式是“键=值”格式
    使用“#”来注释
    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql:///kgc
    username=root
    password=123666
    
    

    储在MySQL数据库中,但在开发和部署时有可能使用不同的数据库,也可能因为客户的需求而更换数据库产品。
    弊端数据库发生改变时,要重新修改代码,重新编译和部署
    解决将数据库信息写在配置文件当中,让程序通过读取配置文件来获得这些信息

    6-4Java中提供了Properties类来读取配置文件

    ResourceBundle rb=ResourceBundle.getBundle(“db”);//直接获得db.properties文件对象;

    方法名说 明
    String getProperty(String key)用指定的键在此属性列表中搜索属性。通过参数key得到其所对应的值
    Object setProperty(String key,String value)调用Hashtable的方法put。通过调用基类的put()方法来设置键-值对
    void load(InputStream inStream)从输入流中读取属性列表 (键和元素对)。通过对指定文件进行装载获取该文件中所有键-值对
    void clear()清除所装载的键-值对,该方法由基类Hashtable提供

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lJVKsCOK-1604303154970)(JDBC/image-20201020221812503.png)]

    6-3-2抽取一个连接对象

    需求:不想传递参数(麻烦),还得保证工具类的通用性。

    解决:配置文件

    jdbc.properties

    url=

    user=

    password=

    1. 抽取一个方法释放资源
     代码实现:
    
    public class JDBCUtils {
    //封装驱动和连接资源的参数【文件的读取,只需要读取一次即可拿到这些值。使用静态代码块】
     private static String url, user, password,driver;
    
    
     
     static{
       //读取资源文件,获取值。
       try {
    
    ​     //1. 创建Properties集合类。
    ​     Properties pro = new Properties();
    ​     //获取src路径下的文件的方式--->ClassLoader 类加载器
    ​     ClassLoader classLoader = JDBCUtils.class.getClassLoader();【通过class对象获得字节码加载器对象】
    ​     URL res = classLoader.getResource("jdbc.properties");
    //inputStream in=classloader.getResourceAsStream("jdbc.properties");【通过类加载方法获得输入流】
    ​     String path = res.getPath();
    
    ​     System.out.println(path);///D:/IdeaProjects/hou/out/production/day04_jdbc/jdbc.properties
    
     
    
    ​     //2. 加载文件
    //pro.load(in);
    ​     // pro.load(new FileReader("D:IdeaProjectshouday04_jdbcsrcjdbc.properties"));
    ​     pro.load(new FileReader(path));
    
     
    
    ​     //3. 获取数据,赋值
    ​     url = pro.getProperty("url");
    ​     user = pro.getProperty("user");
    ​     password = pro.getProperty("password");
    ​     driver = pro.getProperty("driver");
    
    ​     //4. 注册驱动
    ​     Class.forName(driver);
    
       } catch (IOException e) {
    ​     e.printStackTrace();
       } catch (ClassNotFoundException e) {
    ​     e.printStackTrace();
       }
     }
    
     //M1获取连接
     public static Connection getConnection() throws SQLException {
       return DriverManager.getConnection(url, user, password);
    
     }
    
     //M2增删改释放资源:
     public static void close(Statement stmt,Connection conn)throws Exception{
       if( stmt != null){  stmt.close(); }
       if( conn != null){ conn.close();  }
     }
     
    //M3.查询释放资源
     public static void close(ResultSet rs,Statement stmt, Connection conn){
       if( rs != null){ rs.close(); }
       if( stmt != null){ stmt.close();}
       if( conn != null){ conn.close();}
       }
    
     }
    }
    
    1. 通过键盘录入用户名和密码

    2. 判断用户是否登录成功

    select from user where username = “” and password = “”;

    如果这个sql有查询结果,则成功,反之,则失败

     步骤:
    
    1. 创建数据库表 user
    CREATE TABLE USER(
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(32),
    PASSWORD VARCHAR(32)
    );
    INSERT INTO USER VALUES(NULL,'zhangsan','123');
    INSERT INTO USER VALUES(NULL,'lisi','234');
    
    2. 代码实现:
    public class JDBCDemo9 {
     public static void main(String[] args) {
       //1.键盘录入,接受用户名和密码
       Scanner sc = new Scanner(System.in);
       System.out.println("请输入用户名:");
       String username = sc.nextLine();
       System.out.println("请输入密码:");
       String password = sc.nextLine();
    
       //2.调用方法
       boolean flag = new JDBCDemo9().login(username, password);
       //3.判断结果,输出不同语句
       if(flag){//登录成功
    ​     System.out.println("登录成功!");
       }else{
    ​     System.out.println("用户名或密码错误!");
       }}
    
     public boolean login(String username ,String password){
       if(username == null || password == null){return false;
       }
    
       //连接数据库判断是否登录成功
       Connection conn = null;
       Statement stmt = null;
       ResultSet rs = null;
    
       //1.获取连接
       try {
    ​    conn = JDBCUtils.getConnection();//2.定义sql
    ​     String sql = "select  from user where username = '"+username+"' and password = '"+password+"' ";//3.获取执行sql的对象
    ​     stmt = conn.createStatement();//4.执行查询
    ​     rs = stmt.executeQuery(sql);//5.判断/ if(rs.next()){//如果有下一行,则返回truereturn true;}else{
    ​       rturn false;}/return rs.next();//如果有下一行,则返回true
       } catch (SQLException e) {
    ​     e.printStackTrace();
       }finally {
    ​     JDBCUtils.close(rs,stmt,conn);
       }
      return false;
                     }
        }
    
    

    7.JDBC控制事务

    1. 事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。

    2. 操作: 1. 开启事务 2. 提交事务 3. 回滚事务

    3. 使用Connection对象来管理事务

    开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务

    在执行sql之前开启事务 提交事务:commit() 当所有sql都执行完提交事务

    回滚事务:rollback()      在catch中回滚事务

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-065NwI33-1604303154970)(JDBC/image-20201020231327127.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hyGMHKt1-1604303154971)(JDBC/image-20201021184000064.png)]

    Connection conn = null;
    PreparedStatement pstmt1 = null;
    PreparedStatement pstmt2 = null;
      try {
    //1.获取连接
    conn = JDBCUtils.getConnection();
    //开启事务
    conn.setAutoCommit(false);
    //2.定义sql
    //2.1 张三 - 500
    String sql1 = "update account set balance = balance - ? where id = ?";
    //2.2 李四 + 500
    String sql2 = "update account set balance = balance + ? where id = ?";
    //3.获取执行sql对象
    pstmt1 = conn.prepareStatement(sql1);
    pstmt2 = conn.prepareStatement(sql2);
    //4. 设置参数
    pstmt1.setDouble(1,500);
    pstmt1.setInt(2,1);
    pstmt2.setDouble(1,500);
    pstmt2.setInt(2,2);
    //5.执行sql
    pstmt1.executeUpdate();
    // 手动制造异常
    int i = 3/0;
    pstmt2.executeUpdate();
    //提交事务
    conn.commit();
    } catch (Exception e) {
    
    //事务回滚
    try {
    if(conn != null) {
    conn.rollback();
    }
    } catch (SQLException e1) {
    e1.printStackTrace();
    }
    e.printStackTrace();
    }finally {
    JDBCUtils.close(pstmt1,conn);
    JDBCUtils.close(pstmt2,null);
    }
    }
    
    
    }
    

    8.数据库连接池

    1. .数据库连接池负责分配**,【管理和释放】数据库连接,**它允许应用程序【重复使用】一个现有的

      数据库连接**,**而不是重新建立一个

      数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中, 这些数据库连接的数量是由最小数

      据库连接数来设定的.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.

      连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数

      超过最大连接数量时,这些请求将被加入到【等待队列】中.

      数据库连接池的最小连接数和最大连接数的设置要考虑到以下几个因素:

      \1. 最小连接数:是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有

      大量的数据库连接资源被浪费.

      \2. 最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将

      被加入到等待队列中,这会影响【以后的数据库操作】

      \3. 如果最小连接数与最大连接数相差很大:那么最先连接请求将会获利,之后超过最小连接数量的连接

      请求等价于建立一个新的数据库连接.不过,这些大于最小连接数的数据库连接在使用完【不会马上被

      释放】,他将被放到连接池中等待【重复使用或是空间超时后】被释放.

      JDBC : JDBC Template

    数据库连接池

    1. 概念:其实就是一个容器(集合),存放数据库连接的容器。

    当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

    1. 好处:1. 节约资源2. 用户访问高效

    2. 实现:

    3. 标准接口:DataSource javax.sql包下的

    4. 方法:

    获取连接:getConnection() 归还连接:Connection.close()。如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接了。而是归还连接

    1. 一般我们不去实现它,有数据库厂商来实现

    2. C3P0:数据库连接池技术

    3. Druid:数据库连接池实现技术,由阿里巴巴提供的

    8-1.C3P0:数据库连接池技术

    步骤:

    1. 导入jar包 (两个) c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar ,

    不要忘记导入数据库驱动jar包java .connector.jar

    1. 定义配置文件:

    名称: c3p0.properties 或者 c3p0-config.xml

    路径:直接将文件放在src目录下即可。

    1. 创建核心对象 数据库连接池对象 ComboPooledDataSource

    2. 获取连接: getConnection

    //1.创建数据库连接池对象
    
       DataSource ds = new ComboPooledDataSource();  
    
     //2. 获取连接对象
    
       Connection conn = ds.getConnection();
    
    

    8-2 Druid:数据库连接池实现技术,由阿里巴巴提供的

    1. 步骤:

    2. 导入jar包 druid-1.0.9.jar

    3. 定义配置文件:

    是properties形式的 可以叫任意名称,可以放在任意目录下3. 加载配置文件。Properties

    1. 获取数据库连接池对象:通过工厂来来获取 DruidDataSourceFactory
    //3.加载配置文件
       Properties pro = new Properties();
       InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
       pro.load(is);
    
       //4.获取连接池对象
       DataSource ds = DruidDataSourceFactory.createDataSource(pro);
    
    
    

    //5.获取连接

    Connection conn = ds.getConnection();

    1. 定义工具类

    8-3. 定义一个类 DBUtils【DruidDataSourceFactory】

    1. 提供静态代码块加载配置文件,初始化连接池对象

    2. 提供方法

    3. 获取连接方法:通过数据库连接池获取连接

    4. 释放资源

    5. 获取连接池的方法

    public class JDBCUtils { //1.定义成员变量 DataSource
    
     private static DataSource ds ;
    
     static{   
    
    try {     //1.加载配置文件
    
    ​     Properties pro = new Properties();   pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));//2.获取DataSource
    
    ​     ds = DruidDataSourceFactory.createDataSource(pro);
    
       } catch (Exception e) {
    
    ​     e.printStackTrace();
    
       } 
    
     }
    
     M1:获取连接
    
     public static Connection getConnection() throws SQLException {
    
       return ds.getConnection();
    
     }
    
    //M2增删改释放资源:
     public static void close(Statement stmt,Connection conn)throws Exception{
       if( stmt != null){  stmt.close(); }
       if( conn != null){ conn.close();  }
     }
    
    //M3.查询释放资源
     public static void close(ResultSet rs,Statement stmt, Connection conn){
       if( rs != null){ rs.close(); }
       if( stmt != null){ stmt.close();}
       if( conn != null){ conn.close();}//归还连接
       }
    
       //M4 获取连接池方法  
    
     public static DataSource getDataSource(){   return ds; }
    
     }
    
    

    8-4Spring JDBC

    Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发

    步骤:

    1. 导入jar包

    2. 创建JdbcTemplate对象。依赖于数据源DataSource

    JdbcTemplate template = new JdbcTemplate(ds);

    1. 调用JdbcTemplate的方法来完成CRUD的操作

    update():执行DML语句。增、删、改语句

    queryForMap():[结果集长度只能是1]

    查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合

    注意:这个方法查询的结果集长度只能是1

    queryForList():查询结果将结果集封装为list集合

    注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中

    query():查询结果,将结果封装为JavaBean对象

    query的参数:RowMapper

    一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装

    new BeanPropertyRowMapper<类型>(类型.class)

    queryForObject:查询结果,将结果封装为对象

    一般用于聚合函数的查询

    1. 练习:

    需求:1. 修改1号数据的 salary 为 10000

    1. 添加一条记录

    2. 删除刚才添加的记录

    3. 查询id为1的记录,将其封装为Map集合

    4. 查询所有记录,将其封装为List

    5. 查询所有记录,将其封装为Emp对象的List集合

    6. 查询总记录数

    import cn.hou.domain.Emp;
    
    import cn.hou.utils.JDBCUtils;
    
    import org.junit.Test;
    
    import org.springframework.jdbc.core.BeanPropertyRowMapper;
    
    import org.springframework.jdbc.core.JdbcTemplate;
    
    import org.springframework.jdbc.core.RowMapper;
    
    import java.sql.Date;
    
    import java.sql.ResultSet;
    
    import java.sql.SQLException;
    
    import java.util.List;
    
    import java.util.Map;
    
     
    
    public class JdbcTemplateDemo2 {
    
     
    
    //Junit单元测试,可以让方法独立执行//. 获取JDBCTemplate对象
    
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
    
    1. 修改1号数据的 salary 为 10000
    
     @Test
    
     public void test1(){//提供SQL语句并执行【更改比较特殊】
    
      String sql = "update emp set salary = 10000 where id = 1001";int count = template.update(sql);
    
    ​    System.out.println(count);
    
     }
    
    
    
     // 2. 添加一条记录
    
      @Test
    
     public void test2(){
    
      String sql = "insert into emp(id,ename,dept_id) values(?,?,?)"; 
    
      int count = template.update(sql, 1015, "郭靖", 10); 
    
      System.out.println(count); 
    
    }
    
    
    
      //3.删除刚才添加的记录
    
      @Test
    
     public void test3(){
    
    ​    String sql = "delete from emp where id = ?";int count = template.update(sql, 1015);
    
    ​    System.out.println(count);
    
     }
    
    //
    
    4.查询id为1001的记录,将其封装为Map集合
    
      注意:这个方法查询的结果集长度只能是1
    
     @Test
    
     public void test4(){
    
    ​    String sql = "select  from emp where id = ? or id = ?";
    
    ​    Map<String, Object> map = template.queryForMap(sql, 1001,1002);
    
    ​    System.out.println(map);
    
     //输出结果为  {id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}
    
     }
    
    
    
    //   5. 查询所有记录,将其封装为List
    
     @Test
    
     public void test5(){
    
    ​    String sql = "select   from emp";
    
    ​    List<Map<String, Object>> list = template.queryForList(sql);for (Map<String, Object> stringObjectMap : list) {
    
    ​      System.out.println(stringObjectMap);}
    
     }//6. 查询所有记录,将其封装为Emp对象的List集合
    
      @Test
    
     public void test6(){
    
    ​    String sql = "select  from emp";
    
    ​    List<Emp> list = template.query(sql, new RowMapper<Emp>() {@Overridepublic Emp mapRow(ResultSet rs, int i) throws SQLException {
    
    ​        Emp emp = new Emp();int id = rs.getInt("id");
    
    ​        String ename = rs.getString("ename");int job_id = rs.getInt("job_id");int mgr = rs.getInt("mgr");
    
    ​        Date joindate = rs.getDate("joindate");double salary = rs.getDouble("salary");double bonus = rs.getDouble("bonus");int dept_id = rs.getInt("dept_id");
    
    
    
    ​       emp.setId(id);
    
    ​       emp.setEname(ename);
    
    ​       emp.setJob_id(job_id);
    
    ​       emp.setMgr(mgr);
    
    ​       emp.setJoindate(joindate);
    
    ​       emp.setSalary(salary);
    
    ​       emp.setBonus(bonus);
    
    ​       emp.setDept_id(dept_id);return emp;}});for (Emp emp : list) { 
    
    ​     System.out.println(emp); 
    
      }
    
     }
    
    
    
      //6. 查询所有记录,将其封装为Emp对象的List集合
    
      @Test
    
     public void test6_2(){
    
    ​    String sql = "select  from emp";
    
    ​    List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));for (Emp emp : list) {
    
    ​      System.out.println(emp);}
    
     }
    
    
    
    //   7. 【查询总记录数】
    
     @Test
    
     public void test7(){
    
    ​    String sql = "select count(id) from emp";
    
    ​    Long total = template.queryForObject(sql, Long.class);
    
    ​    System.out.println(total);
    
     }
    
    }
    
    

    9. 普通的增删查改

    3.1 创建一个类customer

    public class Customer {
    
    
    	private int id;
    	private String name;
    	private String email;
    	private Date birth;
        
    	public Customer() {
    		super();
    	}
    
    	public Customer(int id, String name, String email, Date birth) {
    		super();
    		this.id = id;
    		this.name = name;
    		this.email = email;
    		this.birth = birth;
    	}
    

    3.2 创建jdbc连接,并封装为方法

    //  获取数据库的连接
    	public static Connection getConnection() {
    		Connection connection = null;
    		InputStream is = null;
            try {
    			is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties");
    			Properties ps = new Properties();
    			ps.load(is);
    
    			String user = ps.getProperty("user");
    		String password = ps.getProperty("password");
    			String driverClass = ps.getProperty("driverClass");
    			String url = ps.getProperty("url");
    
                // 创建Driver对象
    			Class clazz = Class.forName(driverClass);
    			Object obj = clazz.newInstance();
    			Driver driver = (Driver) obj;
    
    			// 注册驱动
    			DriverManager.registerDriver(driver);
    			connection = DriverManager.getConnection(url, user, password);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (is != null) {
    				try {
                        is.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    
    		return connection;
    	}
    

    3.3 在操作完成后要进行连接的关闭

    	public static void close(Connection connection, PreparedStatement ps) {
    		if (connection != null) {
    			try {
    				connection.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    
    		if (ps != null) {
    			try {
    				ps.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    
    	public static void close(Connection connection, PreparedStatement ps, ResultSet rs) {
    		close(connection,ps);
    		if(rs != null){
    			try {
    				rs.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}		
    	}
    

    3.4 增删查改操作

    //  对数据库的  增 ,删,改,查
    public class CRUDTest {
    	//  从数据库中查找一条数据
    	@Test
    public void select() throws Exception {
    		Customer customer = getCustomerById();
    		System.out.println(customer);
    		List<Customer> customers = getCustomers();
    		for (Customer customer2 : customers) {
    			System.out.println(customer2);
    		}
    	}
    
    	//  查询多条数据
    	public List<Customer> getCustomers() throws Exception {
    Connection connection = JDBCUtils.getConnection();
    		String sql = "select   from customers";
    		// 2.预编译  -- 如果没有占位符可以不填充数据
    		PreparedStatement ps = connection.prepareStatement(sql);
    		// 4.执行sql语句
    		ResultSet rs = ps.executeQuery(); // 查找的结果都已经放到ResultSet中了
    		List<Customer> list = new ArrayList<>();
    	while(rs.next()){
          	int id = rs.getInt("id");
    			String name = rs.getString("name");
    			String email = rs.getString("email");
    			Date birth = rs.getDate("birth");
    			//将每条数据放入集合中
    		list.add(new Customer(id, name, email, birth));
    		}
    
    		// 6.关闭资源
    		JDBCUtils.close(connection, ps, rs);
    		return list;
    }
    
    	  //查询一条数据
    
    	public Customer getCustomerById() throws Exception {
    		Connection connection = JDBCUtils.getConnection();
    	String sql = "select  from customers where id = ?";
    // 2.预编译
    		PreparedStatement ps = connection.prepareStatement(sql);
    // 3.填充数据
          ps.setInt(1, 20);
    	// 4.执行sql语句
    		ResultSet rs = ps.executeQuery(); // 查找的结果都已经放到ResultSet中了
    	Customer customer = null;
    	// 5.取数据【根据下标或者字符段名称】
            if (rs.next()) { // 如果有数据就返回true,根据列的索引获取对应的列上的值
                // int id = rs.getInt(1);             
                // String name = rs.getString(2);
    			// String email = rs.getString(3);
    			// Date date = rs.getDate(4);
    			// 获取列上值的第二种方式
    			int id = rs.getInt("id");
    			String name = rs.getString("name");
    			String email = rs.getString("email");
    			Date birth = rs.getDate("birth");// 考虑将数据进行封装】
    			customer = new Customer(id, name, email, birth);
                // 输出获取到的内容
    			System.out.println(id + " " + name + " " + email + " " + birth);
    		}
    	// 6.关闭资源
    		JDBCUtils.close(connection, ps, rs);
    		return customer;
    }
    
    	  //向数据库中插入一条数据
    	@Test
    	public void insert() {
            //多个方法作为局部变量单独声明
    		Connection connection = null;
    		PreparedStatement ps = null;
    		try {
    			// 1 : 连接数据库
    			connection = JDBCUtils.getConnection();
    		// sql语句
    			String sql = "INSERT INTO customers(NAME,email,birth) " + "VALUES(?,?,?);";
    			// 2.预编译
    		ps = connection.prepareStatement(sql);
    		// 3.设置内容
    			ps.setString(1, "强哥"); // 第一个参数:第几个问号 第二个参数:内容
    		ps.setString(2, "qiangge@qq.com");
    		// 获取一个sql下的Date
    			Date date = new Date(new java.util.Date().getTime());
    			ps.setDate(3, date);
    			// 4.执行sql语句
    			ps.execute(); // 如果是查询语句返回true
                //或者int i=ps.executeUpdate();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    		// 5.关闭资源
    			JDBCUtils.close(connection, ps);
    		}
    	}
    
    	  //删除一条件数
    		@Test
    	public void delete() throws Exception {
    	// 1. 获取数据库的连接
    		Connection connection = JDBCUtils.getConnection();
    		String sql = "DELETE FROM customers WHERE id = ?";
    		// 2. 预编译
    		PreparedStatement ps = connection.prepareStatement(sql);
    	// 3.填充数据
    		ps.setInt(1, 19);
    		// 4.执行sql语句
    		int executeUpdate = ps.executeUpdate();
    		System.out.println(executeUpdate + "条受到影响");
    // 5.关闭资源
    		JDBCUtils.close(connection, ps);
    	}
    
    	  //修改一条件数
    		@Test
    	public void update() throws Exception {
    		Connection connection = null;
    		PreparedStatement ps = null;
    		try {
    		connection = JDBCUtils.getConnection();
    			String sql = "UPDATE customers SET NAME = ? WHERE id = ?";
    			ps = connection.prepareStatement(sql);
    			ps.setString(1, "成哥");
    			ps.setInt(2, 18);
    	int executeUpdate = ps.executeUpdate();
    System.out.println(executeUpdate + "条数据受到影响");
    		} catch (Exception e) {
    	e.printStackTrace();
    } finally {
    			JDBCUtils.close(connection, ps);
    		}
    	}
    }
    

    10.通用增删查改CRUD【create,read,update,delete】

    【获得表结构】getMetaData()

    1、使用rs.getMetaData().getTableName(1))就可以返回表名

    2、rs.getMetaData().getColumnCount()字段数
    3、rs.getMetaData().getColumnName(i));字段名

    创建类 User.java

    public class User {
        private int id;
    	private String name;
        private String address;
    	private String phone;
    

    4.1 创建通用连接方案 - 通用增删改

    //	  通用的增删改
    	public static int UID(String sql,Object ...objects) {
    		Connection connection = null;
    		PreparedStatement ps = null;
             int executeUpdate = -1;
    		try {
    			connection = JDBCUtils.getConnection();
                ps = connection.prepareStatement(sql);
    			for (int i = 0; i < objects.length; i++) { // i 表示索引
    				ps.setObject(i + 1, objects[i]); // i + 1表示的是第几个占位符
    			}
    			executeUpdate = ps.executeUpdate();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally{
               JDBCUtils.close(connection, ps);
    		}
    		return executeUpdate;
    	}
    

    测试代码:

    //	  测试通用的增删改
    	@Test
    	public void insert(){
    		String sql = "INSERT INTO customers(NAME,email,birth) VALUES(?,?,?)";
    	Date date = new java.sql.Date(new java.util.Date().getTime());
    		int uid = JDBCUtils.UID(sql, "强哥","qiangge@qq.com",date);
    		System.out.println(uid + "条数据受到影响");
    	}
    

    4.2 通用查找(一条或多条)

    只查一条数据:

    //	  通用的查找 (只有一条数据)
    	  Class<T> clazz : 运行时类的对象
    public static <T> T getObject(Class<T> clazz,String sql,Object ...objects) throws Exception{
    		Connection connection = JDBCUtils.getConnection();
    		PreparedStatement ps = connection.prepareStatement(sql);
    		for (int i = 0; i < objects.length; i++) {
    			ps.setObject(i + 1, objects[i]);
    		}
    	//4.执行sql语句
    		ResultSet rs = ps.executeQuery();
    		
    		//获取列的数量
    		int columnCount = rs.getMetaData().getColumnCount();
    		//创建对象
    		T t = clazz.newInstance();
           while(rs.next()){ //遍历每一条数据
    			for (int i = 0; i < columnCount; i++) {
    //获取某列的列名(如果有别名获取的是别名)
    				String columnLabel = rs.getMetaData().getColumnLabel(i + 1) 
     //通过列名获取列中的数据。
    				Object value = rs.getObject(rs.getMetaData().getColumnLabel(i + 1));
    
    				//封装
    				//通过反射 - 给对象中的属性进行赋值
    				//将表中的列名当作类中的属性名。如果列名和属性名不一样,可以通过别名的方式(别名 = 属性名)
    				//通过列名就获取到了类中的对应的属性
    			Field declaredField = clazz.getDeclaredField(columnLabel);
    				declaredField.setAccessible(true);
    
    			//  第一个参数 : 是给哪个对象进行赋值
    //				  第二个参数 : 属性值
    				declaredField.set(t, value);
    			}
    		}
    		//关闭资源
    BCUtils.close(connection, ps, rs);
    		return t;
    }
    

    查多条数据:

    //	  通用的查找 (返回多条数据)
    	public static <T> List<T> getObjects(Class<T> clazz,String sql,Object ...objects) throws Exception{
    //1.获取数据库的连接
    	Connection connection = JDBCUtils.getConnection();
    //2.预编译
    		PreparedStatement ps = connection.prepareStatement(sql);
    	//3.填充数据
    		for (int i = 0; i < objects.length; i++) {
    			ps.setObject(i + 1, objects[i]);
    		}
    	//4.执行sql语句
    		ResultSet rs = ps.executeQuery();
    		ResultSetMetaData md = rs.getMetaData(); //获取元数据。
    	//获取列的数量
    	int columnCount = md.getColumnCount();
    	//创建一个集合
    		List<T> list = new ArrayList<>();
    		while(rs.next()){ //遍历每一条数据
    			//创建对象
    			T t = clazz.newInstance();
    //			  第一个问题 : 如何获取到表的列数
    //			  第二个问题 : 需要知道类中的属性
    //			  第三个问题 : 对象中属性的名字怎么来
    			for (int i = 0; i < columnCount; i++) {
    				//获取某列的列名(如果有别名获取的是别名)
    				String columnLabel = md.getColumnLabel(i + 1); 
    				 //通过列名获取列中的数据。
    				Object value = rs.getObject(columnLabel);
    				//封装
    			//通过反射 - 给对象中的属性进行赋值
    				//将表中的列名当作类中的属性名。如果列名和属性名不一样,可以通过别名的方式(别名 = 属性名)
    				//通过列名就获取到了类中的对应的属性
    			Field declaredField = clazz.getDeclaredField(columnLabel);
    				declaredField.setAccessible(true);
    				  第一个参数 : 是给哪个对象进行赋值
    				  第二个参数 : 属性值
    				declaredField.set(t, value);
    			}
    			//将对象放入到集合中
    			list.add(t);
    		}
    		//关闭资源
    		JDBCUtils.close(connection, ps, rs);
    		return list;
    	}
    

    测试代码:

                    String sql = "select id,name,email,birth from customers where id = ?";
    		Customer customer = getObject(Customer.class, sql, 5);
    		System.out.println(customer);
    		sql = "select  from users where id = ?";
    		User object = getObject(User.class, sql, 1);
    		System.out.println(object);
        	sql = "select  from users";
    		List<User> users = getObjects(User.class, sql);
    		for (User user : users) {
    			System.out.println(user);
    		}
    

    11.持久化

    将程序中的数据在瞬时状态和持久状态间转换的机制即为数据持久化

    12.单例模式【含饿汉模式懒汉模式】

    12-1单例模式

    系统运行期间,有且仅有一个实例
    一个类只有一个实例——最基本的要求
    只提供私有构造器;它必须自行创建这个实例
    定义了静态的该类私有对象;它必须自行向整个系统提供这个实例
    提供一个静态的公有方法,返回创建或者获取本身的静态私有对象

    若在并发,它严重的弊端,线程不安全,很有可能会出现多个configManager实例,所以在实际开发应用中并不会使用上述方式来实现单例

    12-2饿汉懒汉模式

    单例模式懒汉模式饿汉模式
    概念在类加载时不创建实例,采用延迟加载的方式,在运行调用时创建实例在类加载的时候,就完成初始化
    特点类加载速度快,但是运行时获取对象的速度较慢。——“时间换空间”类加载较慢,但获取对象速度快。——“空间换时间”
    延迟加载(lazy loa ding)具备不具备
    线程安全线程不安全线程安全

    13.登录:

    通过预编译对象查询到用户名是否存在,然后通过结果集获得密码,如果密码匹配则登录成功。否则密码不正确,登陆失败

    13-1流程图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-laWMR7Kg-1604303154971)(JDBC/image-20201022094143479.png)]

    package cn.kgc.tangcco.test1021;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.Scanner;
    
    public class TestLogin {
      public static void main(String[] args) throws SQLException {
    	Scanner input = new Scanner(System.in);
    	System.out.println("请输入用户名");
    	String userName=input.next();
    	System.out.println("请输入密码");
    	String userPwd=input.next();
    	Connection con=null;
    	PreparedStatement stm=null;
    	ResultSet rs=null;
    	try {
    //		1.连接驱动
    		Class.forName("com.mysql.cj.jdbc.Driver");
    //		2.获得连接
    		con=DriverManager.getConnection("jdbc:mysql:///kgc?useUnicode=true&characterEncoding=utf-8", "root", "123456");
    //		3.写sql语句,预编译,并执行sql语句
    		String sql="select  from student where student_name=?";
    		stm=con.prepareStatement(sql);
    		stm.setString(1, userName);
    		rs=stm.executeQuery();
    //		4.执行;
    	boolean	existsUserName=false;
    	String pwd=null;
    	while (rs.next()) {
    		existsUserName=true;
    		 pwd=rs.getString("login_password");
    	}
    	if (existsUserName) {
    		if (pwd.equals(userPwd)) {
    			System.out.println("登录成功,欢迎"+userName);
    		}else {
    			System.out.println("密码或账号不正确");
    		}
    		
    	}else {
    		System.out.println("密码或账号不正确");
    	}
    	} catch (Exception e) {
    		e.printStackTrace();
    	}finally {
    		if (rs!=null) {
    			rs.close();
    		}
    		if (stm!=null) {
    			stm.close();
    			
    		}
    		if (con!=null) {
    			con.close();
    		}
    	}
    }
    }
    /
     
     请输入用户名
    孙福祥
    请输入密码
    22
    登录成功,欢迎孙福祥
      /
    

    14安全套接字协议SSL与HTTPS

    随着互联网的发展,给我们的生活带来便利的同时,也伴随着很多网络钓鱼、信息泄露、网络诈骗等事件的频繁发生,企业网站被钓鱼网站仿冒,遭受经济损失,影响品牌形象。

    如果网站不使用SSL证书,数据以HTTP明文传输,极容易被第三方监听、截取和篡改,而导致用户信息被泄露,给在线用户带来直接损失。

    而部署SSL证书后能确保信息传输的安全性,可防止信息泄露。

    14-1、SSL(安全套接字层)

    SSL(Secure Sockets Layer安全套接字协议),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层与应用层之间对网络连接进行加密。

    SSL证书是数字证书(数字证书包括:SSL证书、客户端证书、代码签名证书等)的一种,因为配置在服务器上也称为服务器SSL证书。SSL证书就是遵守SSL协议,由受信任的数字证书颁发机构CA(如:沃通CA)在验证服务器身份后颁发的一种数字证书。

    使用SSL证书的优势:

    · SSL证书用于实现数据加密传输,防止数据被泄露和篡改

    · 用于认证服务器身份,防范被钓鱼网站攻击

    · 用于消除浏览器地址栏发出的“不安全”的警告

    · 提高SEO搜索引擎排名

    · 提升用户对网站的信任

    · 有助于提高网站的在线销售业绩

    网站加密算法RSA,DSA,ECDSA;

    14-2、HTTPS(安全超文本传输协议)

    HTTPS (全称:Hyper Text Transfer Protocol over SecureSocket Layer),是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性。HTTPS 在HTTP 的基础下加入SSL层,HTTPS的安全基础是 SSL,因此加密的详细内容就需要 SSL。 HTTPS 存在不同于 HTTP 的默认端口及一个加密/身份验证层(在 HTTP与TCP之间)。这个系统提供了身份验证与加密通讯方法。

    网站使用HTTPS的原因有很多:

    · HTTPS有助于在服务器和浏览器之间建立安全通信

    · 它可以保护网站免受篡改或窃听

    · 它可以保护用户免受中间人攻击

    · 各大主流浏览器纷纷要求网站从HTTP升级HTTPS访问

    · 它广泛地被银行、医疗、电子商务、社交媒体和政府等行业使用

    三、SSL证书申请

    安全可信的SSL证书需要向CA机构(证书授权颁发中心)申请,通过严格的审查后才给予颁发。

    如果是个人网站,建议选择DVSSL证书。申请者只需要验证域名管理权,10-50分钟颁发,无需递交纸质文件,也不需要确认申请者单位身份,是一种非常经济的 SSL证书!

    如果是中小型企业网站、电子商务网站,建议选择OVSSL证书。申请者需要通过证书颁发机构的审核。审核内容包括企业身份和域名所有权,以证明申请单位是一个合法存在的真实主体,CA机构将在人工核实后签发证书。

    EVSSL 证书具有最高级别可信度及安全性,需要通过极其严格的审核。审核内容包括企业身份,地址,电话等信息的真实性,以及域名所有权,确保网站身份的真实可靠,是访问者最值得信赖的 SSL 证书。这种证书能在浏览器地址栏显示公司名称,从而使访问者更加放心相信他们所进行交易的网站是真实合法的,提升在线交易量。

    !完成SSL证书的申请和安装流程。您可以访问SSL盾官网,选择SSL证书类型和品牌,自助申请,完成域名验证,等待审核通过即可下载SSL证书,最后安装部署到服务器上即可。【ssl证书作用个人信息,支付安全,私密信息,交易数据】

    
    

    15.三层架构【实体类作为参数贯穿于三层,不属于任何一层】

    【业务逻辑层 Business Logic LayeDAL 是数据访问层 Data Access Layer用户界面(User Interface) 】

    • 1、【实体类user】作为参数贯穿于三层之间;

    • 2、通过传参、方法调用来实现功能;

    • 3、各层之间各负其责;互不影响

      15-1三层架构定义

      就是为了符合“高内聚,低耦合”思想,把各个功能模块划分为表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构,各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体,不同的对象模型的实体类一般对应于数据库的不同表,实体类的属性与数据库表的字段名一致。 [1]

      15-2三层架构区分层次的目的

      是为了 “高内聚,低耦合”。开发人员分工更明确,将精力更专注于应用系统核心业务逻辑的分析、设计和开发,加快项目的进度,提高了开发效率,有利于项目的更新和维护工

      15-3各层定义

    UI(表现层):【与用户交互、展示数据】 主要是指与用户交互的界面。用于接收用户输入的数据和显示处理后用户需要的数据。

    界面交互设计的原则
    统一性原则
    界面风格统一
    用相同方式展现相同类型的数据,如:日期类型
    交互风格统一
    用相同方式完成相同类型的操作,如:录入日期
    美观性原则
    界面美观大方
    易用性原则
    操作方式自然、易理解
    

    BLL:(业务逻辑层): 【控制业务流程及事务】UI层和DAL层之间的桥梁。实现业务逻辑。业务逻辑具体包含:验证、计算、业务规则等等。

    DAL:(数据访问层):【实现数据库操作】 与数据库打交道。主要实现对数据的增、删、改、查。将存储在数据库中的数据提交给业务层,同时将业务层处理的数据保存到数据库。(当然这些操作都是基于UI层的。用户的需求反映给界面(UI),UI反映给BLL,BLL反映给DAL,DAL进行数据的操作,操作后再一一返回,直到将用户所需数据反馈给用户

    **【Entity(实体层):**它不属于三层中的任何一层,但是它是必不可少的一层。】

    15-4Entity在三层架构中的作用:

    • 1、实现面向对象思想中的"封装";
    • 2、贯穿于三层,在三层之间传递数据;(注:确切的说实体层贯穿于三层之间,来连接三层)
    • 3、对于初学者来说,可以这样理解:每张数据表对应一个实体,即每个数据表中的字段对应实体中的属性(注:当然,事实上不是这样。为什么?1>,可能我们需要的实体在数据表对应的实体中并不存在;2>,我们完全可以将所有数据表中的所有字段都放在一个实体里)
    • 4、每一层(UI—>BLL—>DAL)之间的数据传递(单向)是靠变量或实体作为参数来传递的,这样就构造了三层之间的联系,完成了功能的实现。

    15-5三层架构的优劣势

    三层架构的优势:

    • 1,结构清晰、耦合度低
    • 2,可维护性高,可扩展性高
    • 3,利于开发任务同步进行, 容易适应需求变化

    三层架构的优劣势:

    • 1、降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。

    • 2、有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码

    • 3、增加了代码量,增加了工作量

      15-6分层的特点及原则

    分层的特点

    每一层都有自己的职责分层结构中,不同层之间通过【实体类】传输数据
    上一层不用关心下一层的实现细节,上一层通过下一层提供的对外接口来使用其功能
    上一层调用下一层的功能,下一层不能调用上一层功能

    分层原则1——【顺序访问原则】下一层为上一层服务,但不使用上层的服务

    分层原则2——【封装性】原则 每个层次向外【公开接口】,但是隐藏内部细节

    面向接口编程:只关系实现的功能,不关心具体的实现细节

    分层开发的优势

    代码复用
    职责清晰,分工明确,分离开发人员的关注
    无损替换【工具类之间切换,比如MySQL,切换成Oracle;当前层替换】
    降低了系统间的依赖利于维护扩展

    16.JDBCUtils工具类和DBUtils工具类不同点【其实两者没有区别,可以自己自定义是否进行加载配置文件或c3p0使用连接池】也可以封装进去BaseDao

    dbutils 封装了driver,url,root,pwd运用的是 连接池工具,或者properies配置文件;使用了数据连接池;

    不用专门关闭资源,只是归还连接;

    BaseDao中工具都是私有的静态的。

    1.7版本以后有个直接获得配置文件的方法,不用输出流

    package cn.kgc.tangyingli.utils;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ResourceBundle;
    
    /**
     *
     工具类
     * */
    public class DBUtil {
    static Connection con= null;
    static PreparedStatement stm=null;
    static ResultSet rs=null;
    //获得连接方法
    ResourceBundle rb=ResourceBundle.getBundle("db");//直接获得db.properties文件对象;
    public static Connection getConnection() {
    	try {
    		Class.forName("com.mysql.cj.jdbc.Driver");
    		con=DriverManager.getConnection("jdbc:/mysql:///kgc&useSSL=true", "root", "123456");
    	} catch (Exception e) {
    		
    		e.printStackTrace();
    	}
    	return con;
    }
    //关闭资源方法
    public static void releaseResources(Connection con,ResultSet rs,PreparedStatement stm) {
    	try {
    		if (rs!=null) {
    			rs.close();
    		}
    		if (stm!=null) {
    			stm.close();
    		}
    		if (con!=null) {
    			con.close();
    		}
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    	
    }
    //增删改通用方法
    public  static int update(String sql, Object...objects) {
    	con=getConnection();
    	int result=0;
    	try {
    		stm=con.prepareStatement(sql);
    		if (objects!=null) {
    			for (int i = 0; i < objects.length; i++) {
    				stm.setObject(i+1, objects[i]);
    			}
    		}
    	result=	stm.executeUpdate();
    		
    	} catch (SQLException e) {
    		
    		e.printStackTrace();
    	}finally {
    		releaseResources(con, null, stm);
    	}
    	return result;
    }
    
    }
    

    封装jdbc工具时,增删改通用方法可以返回值改为布尔类型,那么,查询的方法只需要多加一句用结果集接收即可

    17三大连接池

    17-1properties创建方法

    **方法一、**eclipse 方法: 打开file–new–other 选择general–file–next 在file name后输入:文件名.properties,finish即可。

    **方法二、**新建普通的文本文件,然后修改后缀为properties即可创建。

    **方法三、**如果是编程实现的话,使用输出流,输出保存时后缀文件是properties即可配置文件

    使用c3p0连接池时ssl安全套字协议必须默认为false。【配置文件用连接池时用true/false均可】

    使用配置文件原因,解耦合

    数据库工作累,封装了jdbc操作的常用功能;

    数据库的相关信息是写在源文件中的,如果我们要修改数据库,就必须要切换源码,;我们应该降低代码的耦合度,源代码一点都不需要改动;

    配置文件一定要放在src文件夹下面,里面是常量,每个常量的内容后面不能加空格或者引号;

    【ResourceBundle】资源包

    ResourceBundle rb=ResourceBundle.getBundle(“db”);//直接获得db.properties文件对象;【相当于25-33行的代码】

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tiPhnh19-1604303154972)(JDBC/image-20201023200336991.png)]

    useSSL=true&verifyServerCertificate=false
    

    17-2MySQL在高版本需要指明是否进行SSL连接。

       SSL协议提供服务主要: 		
           1)认证用户服务器,确保数据发送到正确的服务器;    .
           2)加密数据,防止数据传输途中被窃取使用;
           3)维护数据完整性,验证数据在传输过程中是否丢失;
    
       当前支持SSL协议两层:
       	 	SSL记录协议(SSL【Record 】Protocol):建立靠传输协议(TCP)高层协议提供数据封装、压缩、加密等基本功能支持
    	    SSL握手协议(SSL 【Handshake】 Protocol):建立SSL记录协议用于实际数据传输始前通讯双进行身份认证、协商加密
    	    算法、 交换加密密钥等。
    

    在mysql连接字符串url中加入ssl=true或者false即可

    c3p0dbcp****区别

    dbcp没有自动回收空闲连接的功能

    c3p0有自动回收空闲连接功能

    #properties
    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:3306/kgc? useUnicode=true&characterEncoding=utf8&useSSL=false;
    com.mysql.username=root
    com.mysql.password=123456
    
    
    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
        <default-config>
            <!-- 必填 -->
            <!-- 驱动类 -->
            <property name="driver">com.mysql.jdbc.Driver</property>
            <!-- URL -->
            <property name="url">jdbc:mysql://localhost:3306/kgc? useUnicode=true&characterEncoding=utf8&useSSL=false</property>
            <!-- 账号 -->
            <property name="user">root</property>
            <!-- 密码 -->
            <property name="password">root</property>
            <!-- 可选 -->
            <!-- 初始连接数 -->
            <property name="initialPoolSize">10</property>
            <!-- 最大闲置时间 -->
            <property name="maxIdleTime">30</property>
            <!-- 最大连接数 -->
            <property name="maxPoolSize">100</property>
            <!-- 最小连接数 -->
            <property name="minPoolSize">10</property>
            <!-- 最大SQL语句数 -->
            <property name="maxStatements">200</property>
        </default-config>
    </c3p0-config>
    

    17-3c3p0,dbcp,druid深入了解

    1)DBCP
    
       DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池.DBCP可以直接的在应用程序中使用,Tomcat的数据源使用的就是DBCP。
    
      2)c3p0
    
       c3p0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。
    
     3)Druid
    
       阿里出品,淘宝和支付宝专用数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个 SQL Parser。支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等等。Druid针对Oracle和MySql做了特别优化,比如Oracle的PS Cache内存占用优化,MySql的ping检测优化。Druid提供了MySql、Oracle、Postgresql、SQL-92的SQL的完整支持,这是一个手写的高性能SQL Parser,支持Visitor模式,使得分析SQL的抽象语法树很方便。简单SQL语句用时10微秒以内,复杂SQL用时30微秒。通过Druid提供的SQL Parser可以在JDBC层拦截SQL做相应处理,比如说分库分表、审计等。Druid防御SQL注入攻击的WallFilter就是通过Druid的SQL Parser分析语义实现的。
    

    基本配置是指连接池进行数据库连接的四个基本必需配置:

    传递给JDBC驱动的用于连接数据库的用户名、密码、URL以及驱动类名。

    DBCPc3p0Druid
    用户名usernameuserusername
    密码passwordpasswordpassword
    URLurljdbcUrljdbcUrl
    驱动类名driverClassNamedriverClassdriverClassName
    最小连接数minIdle(0)minPoolSize(3)minIdle(0)
    初始化连接数initialSize(0)initialPoolSize(3)initialSize(0)
    最大连接数maxTotal(8)maxPoolSize(15)maxActive(8)
    最大等待时间maxWaitMillis(毫秒)maxIdleTime(0秒)maxWait(毫秒)
    开启缓存功能poolPreparedStatementsmaxStatementspoolPreparedStatements
    单个连接拥有的最大缓存数maxOpenPrepared- StatementsmaxStatementsPer- ConnectionmaxOpenPrepared- Statement
    申请连接检测testOnBorrowtestConnectionOnCheckintestOnBorrow
    是否超时检测testWhileIdletestWhileIdle
    空闲时间timeBetweenEvictionRunsMillisidleConnectionTestPeriodtimeBetweenEvictionRunsMillis
    校验用sql语句validationQuerypreferredTestQueryvalidationQuery
    归还连接检测testOnReturntestConnectionOnCheckouttestO
    是否超时关闭连接removeAbandonedbreakAfterAcquireFailureremoveAbandoned
    超时时间removeAbandonedTimeoutcheckoutTimeoutremoveAbandonedTimeout
    是否记录日志logAbandonedlogAbandoned
    DBCPc3p0Druid
    重连次数acquireRetryAttempts
    间隔时间acquireRetryDelay

    17-4 DBCP 属性说明表**

    属性(Parameter)默认值(Default)描述(Description)
    username传递给JDBC驱动的用于建立连接的用户名(The connection username to be passed to our JDBC driver to establish a connection.)
    password传递给JDBC驱动的用于建立连接的密码(The connection password to be passed to our JDBC driver to establish a connection.)
    url传递给JDBC驱动的用于建立连接的URL(The connection URL to be passed to our JDBC driver to establish a connection.)
    driverClassName使用的JDBC驱动的完整有效的java 类名(The fully qualified Java class name of the JDBC driver to be used.)
    defaultAutoCommitdriver default连接池创建的连接的默认的auto-commit状态,没有设置则不会自动提交(The default auto-commit state of connections created by this pool. If not set then the setAutoCommit method will not be called.)
    initialSize0初始化连接:连接池启动时创建的初始化连接数量(The initial number of connections that are created when the pool is started.
    maxTotal8最大活动连接:连接池在同一时间能够分配的最大活动连接的数量, 如果设置为非正数则表示不限制(The maximum number of active connections that can be allocated from this pool at the same time, or negative for no limit.)
    maxIdle8最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制(The maximum number of connections that can remain idle in the pool, without extra ones being released, or negative for no limit.)
    minIdle0最小空闲连接:连接池中容许保持空闲状态的最小连接数量,负数表示没有现在(The maximum number of connections that can remain idle in the pool, without extra ones being released, or negative for no limit.)
    注意:如果在某些负载比较大的系统中将maxIdel设置过小时,很可能会出现连接关闭的同时新连接马上打开的情况.这是由于关闭连接的线程比打开的快导致的.所以,对于这种系统中,maxIdle的设定值是不同的但是通常首选默认值
    (NOTE: If maxIdle is set too low on heavily loaded systems it is possible you will see connections being closed and almost immediately new connections being opened. This is a result of the active threads momentarily closing connections faster than they are opening them, causing the number of idle connections to rise above maxIdle. The best value for maxIdle for heavily loaded system will vary but the default is a good starting point.)
    maxWaitMillisindefinitely最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数),超过时间则抛出异常,如果设置为-1表示无限等待(The maximum number of milliseconds that the pool will wait (when there are no available connections) for a connection to be returned before throwing an exception, or -1 to wait indefinitely.)
    validationQuerySQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前.如果指定,则查询必须是一个SQL SELECT并且必须返回至少一行记录(The SQL query that will be used to validate connections from this pool before returning them to the caller. If specified, this query MUST be an SQL SELECT statement that returns at least one row. If not specified, connections will be validation by calling the isValid() method.)
    testOnCreatefalse指明是否在建立连接之后进行验证,如果验证失败,则尝试重新建立连接(The indication of whether objects will be validated after creation. If the object fails to validate, the borrow attempt that triggered the object creation will fail.)
    testOnBorrowtrue指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个.注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串(The indication of whether objects will be validated before being borrowed from the pool. If the object fails to validate, it will be dropped from the pool, and we will attempt to borrow another.)
    testOnReturnfalse指明是否在归还到池中前进行检验(The indication of whether objects will be validated before being returned to the pool.)
    testWhileIdlefalse指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除.注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串(The indication of whether objects will be validated by the idle object evictor (if any). If an object fails to validate, it will be dropped from the pool.)
    timeBetweenEviction- RunsMillis-1在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位.如果设置为非正数,则不运行空闲连接回收器线程(The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no idle object evictor thread will be run.)
    numTestsPerEvictionRun3在每次空闲连接回收器线程(如果有)运行时检查的连接数量(The number of objects to examine during each run of the idle object evictor thread (if any).)
    minEvictableIdleTime-Millis10006030连接在池中保持空闲而不被空闲连接回收器线程(如果有)回收的最小时间值,单位毫秒(The minimum amount of time an object may sit idle in the pool before it is eligable for eviction by the idle object evictor (if any).)
    softMiniEvictableIdle- TimeMillis-1说明(The minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the idle connection evictor, with the extra condition that at least “minIdle” connections remain in the pool. When miniEvictableIdleTimeMillis is set to a positive value, miniEvictableIdleTimeMillis is examined first by the idle connection evictor - i.e. when idle connections are visited by the evictor, idle time is first compared against miniEvictableIdleTimeMillis (without considering the number of idle connections in the pool) and then against softMinEvictableIdleTimeMillis, including the minIdle constraint.)
    maxConnLifetimeMillis-1说明(The maximum lifetime in milliseconds of a connection. After this time is exceeded the connection will fail the next activation, passivation or validation test. A value of zero or less means the connection has an infinite lifetime.)
    logExpiredConnectionstrue说明(Flag to log a message indicating that a connection is being closed by the pool due to maxConnLifetimeMillis exceeded. Set this property to false to suppress expired connection logging that is turned on by default.
    connectionInitSqlsnull说明(A Collection of SQL statements that will be used to initialize physical connections when they are first created. These statements are executed only once - when the configured connection factory creates the connection.)
    infotrue说明(True means that borrowObject returns the most recently used (“last in”) connection in the pool (if there are idle connections available). False means that the pool behaves as a FIFO queue - connections are taken from the idle instance pool in the order that they are returned to the pool.)
    poolPreparedState-mentsfalse开启池的prepared statement 池功能(Enable prepared statement pooling for this pool.)
    maxOpenPreparedState-mentsunlimitedstatement池能够同时分配的打开的statements的最大数量, 如果设置为0表示不限制(The maximum number of open statements that can be allocated from the statement pool at the same time, or negative for no limit.)
    NOTE - Make sure your connection has some resources left for the other statements. Pooling PreparedStatements may keep their cursors open in the database, causing a connection to run out of cursors, especially if maxOpenPreparedStatements is left at the default (unlimited) and an application opens a large number of different PreparedStatements per connection. To avoid this problem, maxOpenPreparedStatements should be set to a value less than the maximum number of cursors that can be open on a Connection.
    accessToUnderlyingConnectionAllowedfalse控制PoolGuard是否容许获取底层连接(Controls if the PoolGuard allows access to the underlying connection.) 默认false不开启, 这是一个有潜在危险的功能, 不适当的编码会造成伤害.(关闭底层连接或者在守护连接已经关闭的情况下继续使用它).请谨慎使用,并且仅当需要直接访问驱动的特定功能时使用.注意: 不要关闭底层连接, 只能关闭前面的那个. Default is false, it is a potential dangerous operation and misbehaving programs can do harmful things. (closing the underlying or continue using it when the guarded connection is already closed) Be careful and only use when you need direct access to driver specific extensions. NOTE: Do not close the underlying connection, only the original one.
    removeAbandonedfalse标记是否删除泄露的连接,如果他们超过了removeAbandonedTimout的限制.如果设置为true, 连接被认为是被泄露并且可以被删除,如果空闲时间超过removeAbandonedTimeout. 设置为true可以为写法糟糕的没有关闭连接的程序修复数据库连接. (Flags to remove abandoned connections if they exceed the removeAbandonedTimout. A connection is considered abandoned and eligible for removal if it has not been used for longer than removeAbandonedTimeout. Setting one or both of these to true can recover db connections from poorly written applications which fail to close connections.)
    removeAbandonedTimeout300泄露的连接可以被删除的超时值, 单位秒 (Timeout in seconds before an abandoned connection can be removed.)
    logAbandonedfalse标记当Statement或连接被泄露时是否打印程序的stack traces日志。被泄露的Statements和连接的日志添加在每个连接打开或者生成新的Statement,因为需要生成stack trace。(Flag to log stack traces for application code which abandoned a Statement or Connection. Logging of abandoned Statements and Connections adds overhead for every Connection open or new Statement because a stack trace has to be generated.)
    abandonedUsageTrackingfalse如果为true, 那么连接池会记录每个方法调用时候的堆栈信息以及废弃连接的调试信息(If true, the connection pool records a stack trace every time a method is called on a pooled connection and retains the most recent stack trace to aid debugging of abandoned connections. There is significant overhead added by setting this to true.)
    注:如果开启"removeAbandoned",那么连接在被认为泄露时可能被池回收. 这个机制在(getNumIdle() < 2)and (getNumActive() > getMaxActive() - 3)时被触发. 举例当maxActive=20, 活动连接为18,空闲连接为1时可以触发"removeAbandoned".但是活动连接只有在没有被使用的时间超过"removeAbandonedTimeout"时才被删除,默认300秒.在resultset中游历不被计算为被使用.
    If you have enabled removeAbandonedOnMaintenance or removeAbandonedOnBorrow then it is possible that a connection is reclaimed by the pool because it is considered to be abandoned. This mechanism is triggered when (getNumIdle() < 2) and (getNumActive() > getMaxTotal() - 3) and removeAbandonedOnBorrow is true; or after eviction finishes and removeAbandonedOnMaintenance is true. For example, maxTotal=20 and 18 active connections and 1 idle connection would trigger removeAbandonedOnBorrow, but only the active connections that aren’t used for more then “removeAbandonedTimeout” seconds are removed (default 300 sec). Traversing a resultset doesn’t count as being used. Creating a Statement, PreparedStatement or CallableStatement or using one of these to execute a query (using one of the execute methods) resets the lastUsed property of the parent connection.

    17-5 C3P0 属性说明表

    属性(Parameter)默认值(Default)描述(Description)
    user同DBCP中的username属性
    password同DBCP中的password属性
    jdbcUrl同DBCP中的jdbcUrl属性
    driverClass同DBCP中的driverClass属性
    autoCommitOnClosefalse默认值false表示回滚任何未提交的任务,设置为true则全部提交,而不是在关闭连接之前回滚 (C3P0’s default policy is to rollback any uncommitted, pending work.Setting autoCommitOnClose to true causes uncommitted pending work to be committed, rather than rolled back on Connection close.) *参见DBCP中的defaultAutoCommit属性
    initialPoolSize3初始化连接:连接池启动时创建的初始化连接数量(The initial number of connections that are created when the pool is started. *参见DBCP中的initialSize属性
    maxPoolSize15连接池中保留的最大连接数(Maximum number of Connections a pool will maintain at any given time.) *参见DBCP中的maxIdle属性
    minPoolSize3连接池中保留的最小连接数(Minimum number of Connections a pool will maintain at any given time.) *参见DBCP中的maxIdle属性
    maxIdleTime0最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以秒计数),超过时间则抛出异常,如果设置为0表示无限等待(Seconds a Connection can remain pooled but unused before being discarded. Zero means idle connections never expire.) *参见DBCP中maxWaitMillis 属性
    preferredTestQuerynull定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:测试的表必须在初始数据源的时候就存在。(Defines the query that will be executed for all connection tests, if the default ConnectionTester (or some other implementation of QueryConnectionTester, or better yet FullQueryConnectionTester) is being used. Defining a preferredTestQuery that will execute quickly in your database may dramatically speed up Connection tests.)
    testConnectionOn- Checkinfalse如果设为true那么在取得连接的同时将校验连接的有效性。(If true, an operation will be performed asynchronously at every connection checkin to verify that the connection is valid. Use in combination with idleConnectionTestPeriod for quite reliable, always asynchronous Connection testing.) *参见DBCP中的testOnBorrow属性
    testConnectionOn- Checkoutfalse如果设为true那么在每个connection提交的时候都将校验其有效性,但是要确保配置的preferredTestQuery的有效性(If true, an operation will be performed at every connection checkout to verify that the connection is valid. Be sure to set an efficient preferredTestQuery or automaticTestTable if you set this to true.) *参见DBCP中的testOnBorrow属性
    idleConnectionTest- Period0如果设置大于0,表示过了多少秒检查一次空闲连接,结合testConnectionOnCheckin以及testConnectionOnCheckout使用(If this is a number greater than 0, c3p0 will test all idle, pooled but unchecked-out connections, every this number of seconds.)
    acquireRetryAttempts30定义在从数据库获取新连接失败后重复尝试的次数, 如果小于0则表示无限制的连接。(Defines how many times c3p0 will try to acquire a new Connection from the database before giving up. If this value is less than or equal to zero, c3p0 will keep trying to fetch a Connection indefinitely.)
    acquireRetryDelay1000两次连接中的间隔时间,单位毫秒。(Milliseconds, time c3p0 will wait between acquire attempts.)
    breakAfterAcquire- Failurefalse获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调用 getConnection() 的时候继续尝试获取连接。如果为 true,那么在尝试获取连接失败后该数据源将声明已断开并永久关闭。(If true, a pooled DataSource will declare itself broken and be permanently closed if a Connection cannot be obtained from the database after making acquireRetryAttempts to acquire one. If false, failure to obtain a Connection will cause all Threads waiting for the pool to acquire a Connection to throw an Exception, but the DataSource will remain valid, and will attempt to acquire again following a call to getConnection().)
    checkoutTimeout0当连接池用完时客户端调用 getConnection() 后等待获取新连接的时间,潮湿后将抛出SQLException,如设为0,则为无限期等待。单位毫秒。(The number of milliseconds a client calling getConnection() will wait for a Connection to be checked-in or acquired when the pool is exhausted. Zero means wait indefinitely. Setting any positive value will cause the getConnection() call to time-out and break with an SQLException after the specified number of milliseconds.)
    maxStatements0控制数据源内加载的PreparedStatements数量(Enable prepared statement pooling for this pool.)
    maxStatementsPer- Connection0定义了连接池内单个连接所拥有的最大缓存statements数(The maximum number of open statements that can be allocated from the statement pool at the same time, or negative for no limit.)

    17-6  DRUID 属性说明表

    属性(Parameter)默认值(Default)描述(Description)
    username连接数据库的用户名
    password连接数据库的密码
    jdbcUrl同DBCP中的jdbcUrl属性
    driverClassName根据url自动识别这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName
    initialSize0初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 *参见DBCP中的initialSize属性
    maxActive8最大连接池数量(Maximum number of Connections a pool will maintain at any given time.) *参见DBCP中的maxTotal属性
    maxIdle8已经不再使用,配置了也没效果*参见DBCP中的maxIdle属性
    minIdle最小连接池数量
    maxWait获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
    poolPreparedState- mentsfalse是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。
    maxOpenPrepared- Statements-1要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
    testOnBorrowtrue申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
    testOnReturnfalse归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
    testWhileIdlefalse建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
    validationQuery用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、 testWhileIdle都不会其作用。在mysql中通常为select ‘x’,在oracle中通常为select 1 from dual
    timeBetweenEviction-RunsMillis1) Destroy线程会检测连接的间隔时间 2) testWhileIdle的判断依据
    minEvictableIdle- TimeMillisDestory线程中如果检测到当前连接的最后活跃时间和当前时间的差值大于minEvictableIdleTimeMillis,则关闭当前连接。
    removeAbandoned对于建立时间超过removeAbandonedTimeout的连接强制关闭
    removeAbandoned-Timeout指定连接建立多长时间就需要被强制关闭
    logAbandonedfalse指定发生removeabandoned的时候,是否记录当前线程的堆栈信息到日志中
    filters属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 1)监控统计用的filter:stat 2)日志用的filter:log4j 3)防御sql注入的filter:wall

    18元数据

    简介:metadata一般指元数据元数据Metadata),又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能按应用包括数据结构:数据集的名称、关系、字段、约束等;

    //列的名称
             String columnName = rs_metaData.getColumnName(i + 1);
                // 获取每一行的每一列的值
                Object columnValue = rs.getObject(columnName);
    
    package com;
    
    import java.sql.Connection;
    import java.sql.DatabaseMetaData;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class testMatadata {
    public static void main(String[] args) {
    	 Connection conn=null;
    	//1. JDBC连接MYSQL的代码很标准。 
    	String DRIVER="com.mysql.jdbc.Driver";
        String URL="jdbc:mysql://127.0.0.1:3306/test";
    	String USER="root";
    	String PASSWORD="root";
        try {
        	//1.加载驱动程序
        	Class.forName(DRIVER);
        	//2.获得数据库链接
    		conn=DriverManager.getConnection(URL, USER, PASSWORD);
    	    DatabaseMetaData dbmd = conn.getMetaData();  
    	    ResultSet rs = null;  
            System.out.println("数据库已知的用户: "+ dbmd.getUserName());      
            System.out.println("数据库的系统函数的逗号分隔列表: "+ dbmd.getSystemFunctions());      
            System.out.println("数据库的时间和日期函数的逗号分隔列表: "+ dbmd.getTimeDateFunctions());      
            System.out.println("数据库的字符串函数的逗号分隔列表: "+ dbmd.getStringFunctions());      
            System.out.println("数据库供应商用于 'schema' 的首选术语: "+ dbmd.getSchemaTerm());      
            System.out.println("数据库URL: " + dbmd.getURL());      
            System.out.println("是否允许只读:" + dbmd.isReadOnly());      
            System.out.println("数据库的产品名称:" + dbmd.getDatabaseProductName());      
            System.out.println("数据库的版本:" + dbmd.getDatabaseProductVersion());      
            System.out.println("驱动程序的名称:" + dbmd.getDriverName());      
            System.out.println("驱动程序的版本:" + dbmd.getDriverVersion());    
            System.out.println("数据库中使用的表类型");      
            rs = dbmd.getTableTypes();      
            while (rs.next()) {      
                System.out.println(rs.getString("TABLE_TYPE"));      
            }
            // 获取连接
            PreparedStatement pstmt = conn.prepareStatement("select * from test.user ");
            rs = pstmt.executeQuery();
            // 得到结果集元数据
            //目标:通过结果集元数据,得到列的名称
            ResultSetMetaData rs_metaData = rs.getMetaData();
            while (rs.next()) {
                int count = rs_metaData.getColumnCount();
                for (int i=0; i<count; i++) {
                    // 得到列的名称
                    String columnName = rs_metaData.getColumnName(i + 1);
                    // 获取每一行的每一列的值
                    Object columnValue = rs.getObject(columnName); 
                    System.out.print(columnName + "=" + columnValue + ",\n");
                }
                
            }
        } catch (ClassNotFoundException e) {
    		e.printStackTrace();
    	} catch (SQLException e) {
    		e.printStackTrace();
    	} 
        }
    }
    *****************************************88888
    数据库已知的用户: root@localhost
    数据库的系统函数的逗号分隔列表: DATABASE,USER,SYSTEM_USER,SESSION_USER,PASSWORD,ENCRYPT,LAST_INSERT_ID,VERSION
    数据库的时间和日期函数的逗号分隔列表: DAYOFWEEK,WEEKDAY,DAYOFMONTH,DAYOFYEAR,MONTH,DAYNAME,MONTHNAME,QUARTER,WEEK,YEAR,HOUR,MINUTE,SECOND,PERIOD_ADD,PERIOD_DIFF,TO_DAYS,FROM_DAYS,DATE_FORMAT,TIME_FORMAT,CURDATE,CURRENT_DATE,CURTIME,CURRENT_TIME,NOW,SYSDATE,CURRENT_TIMESTAMP,UNIX_TIMESTAMP,FROM_UNIXTIME,SEC_TO_TIME,TIME_TO_SEC
    数据库的字符串函数的逗号分隔列表: ASCII,BIN,BIT_LENGTH,CHAR,CHARACTER_LENGTH,CHAR_LENGTH,CONCAT,CONCAT_WS,CONV,ELT,EXPORT_SET,FIELD,FIND_IN_SET,HEX,INSERT,INSTR,LCASE,LEFT,LENGTH,LOAD_FILE,LOCATE,LOCATE,LOWER,LPAD,LTRIM,MAKE_SET,MATCH,MID,OCT,OCTET_LENGTH,ORD,POSITION,QUOTE,REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX,SPACE,STRCMP,SUBSTRING,SUBSTRING,SUBSTRING,SUBSTRING,SUBSTRING_INDEX,TRIM,UCASE,UPPER
    数据库供应商用于 'schema' 的首选术语: 
    数据库URL: jdbc:mysql://127.0.0.1:3306/test
    是否允许只读:false
    数据库的产品名称:MySQL
    数据库的版本:5.7.26-log
    驱动程序的名称:MySQL Connector Java
    驱动程序的版本:mysql-connector-java-5.1.32 ( Revision: jess.balint@oracle.com-20140716155848-mlwabor66widht1n )
    数据库中使用的表类型:
    LOCAL TEMPORARY
    SYSTEM TABLE
    SYSTEM VIEW
    TABLE
    VIEW
    user_id=1,
    user_name=fanny,
    

    19.面向对象补充【通过接口降低耦合性】

    一个类成为另外一个类的属性,这种关系成为合成/聚合关系,此时其中一个类是另外一个类的一部分;
    一个类成为另外一个类的方法或参数类型,这种关系称为依赖。【不能写人依赖于迈腾,这样代码写死,耦合度太高】
    Person p=new Person();
    Office o=new office();
    Car car=o.getCar("ceo");//返回一个具体的对象,并实现了car接口;【我们不知道具体哪个类,但是代码能运行,代码耦合性降低了】
    p.driver(car);
    多态:用接口或父类声明引用指向实现类或具体子类对象【父类引用指向子类】,动态绑定;
    
    
    封装jdbc工具是,用常量封装user原因,把它放到配置文件里解耦;一定要在src目录下,并且里面的值不能用符号或空格。只用变量=具体值 【类没发现因为没有获得连接,因为配置文件不正确,因为值后面多了空格】
    
    行级锁又称为悲观锁,在当前事务没有结束之前,被锁定的记录,精确到表中的行,其他事务是无法进行修改的
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wXAUWP54-1604303154973)(JDBC/image-20201027233058626.png)]

    batch批处理注意事项,数据量特别大的时候,应该用statement,因为预编译存储数量有限,容易产生异常

    展开全文
  • Java连接数据库实现模糊查询like

    千次阅读 2020-05-31 16:32:41
    第一种方式:直接在SQL语句中进行拼接,此时需要注意的是“参数”在SQL语句中需要用单引号拼接起来 String sql = "select * from bookinfo where bname like '%" + 参数 + "%'"; 第二种方式: 使用占位符,在占位符...

    第一种方式:直接在SQL语句中进行拼接,此时需要注意的是“参数”在SQL语句中需要用单引号拼接起来

    String sql = "select * from bookinfo where bname like '%" + 参数 + "%'";

    第二种方式: 使用占位符,在占位符赋值时进行拼接
    String sql = "select * from bookinfo where bname like ?"; ps.setString(1, "%"+参数+"%");

    展开全文
  • JDBC链接数据库实例 1,加载数据库驱动 2,创建并获取数据库链接 3,创建jdbc statement对象 4,设置sql语句 5,设置sql语句中的参数(用用preparedStatement) 6,通过statemnet执行sql并获取结果 7,对sql...
  • * 更新数据库emp,可以更新的字段为ename,job,sal,comm */ public void updateEmp (Emp emp){ //第一步还是连接数据库 //利用con得到jdbc的getconnection con = jdbc.getconneConnection(); //...
  • 第三节学习MySQL数据库JDBC接口,MyBatis框架等,掌握的数据的存放和管理。 Java数据库开发基础,介绍MySQL数据库JDBC操作数据库、C3P0数据库连接池,Java反射等内容,进行油画商城开发。 3.1.1 MySQL基础之数据...
  • 数据库简单介绍与JDBC

    2020-10-18 18:45:42
    1.数据库 1.1什么是数据库数据库(DB,Data Base) 概念:数据仓库,软件,安装在操作系统( window, linux,mac…)之上!SQL,可以存储大量的数据。500万! 作用:存储数据,管理数据 1.2数据库分类 关系型数据库:...
  • 教室依赖教室房间号) 二、JDBC 1、概述 JDBC(java database collection)是java连接数据库的一套接口,只需要调用接口的方法就能操作数据库,无论是哪种数据库,都是实现了接口方法,面向接口编程。需要下载与数据库...
  • MyBatis面试题(2020最新版)

    万次阅读 多人点赞 2019-09-24 16:40:33
    整理好的MyBatis面试题库,史上最全的MyBatis面试题,...MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plai...
  • 1.1数据库的定义 数据库(DataBase,简称DB),是一个按数据结构来存储和管理数据的计算机软件系统。每个数据库都有一个或多个不同的 API 用于创建,访问,管理,搜索和复制所保存的数据。 概念 : 长期存放在计算机内,...
  • TRIP数据库JDBC

    2017-07-10 19:16:29
    TRIP数据库操作工具类
  • JDBC-Java数据库连接

    2020-08-16 23:50:28
    JDBC1、JDBC是什么?2、JDBC的本质?3、JDBC开发前的准备工作: 先从官网下载对应的驱动jar包,然后将其配置到环境变量classpath当中4、JDBC...  Java DataBase Connectivity(Java数据库连接) 2、JDBC的本质? JDBC
  • JDBC提供了一个 Java API 来读取存储在数据库表中的实际数据。除此之外,还可以使用相同的 API 读取有关数据库的元数据。元数据是指有关数据的数据,例如表名、列名和列类型。 本文介绍 如何使用DatabaseMetaData...
  • web前端,数据库jdbc

    千次阅读 2018-09-27 22:15:16
    - 数据库就是一个存储数据的仓库,本质就是一个文件系统,数据库是按照特定的格式把数据存储起来,用户可以对存储的数据进行增删改查操作 ###DBMS - DataBaseManagementSystem:数据库管理系统(软件) - 什么是...
  • //根据性别和姓名的模糊查询查找学生 String sql = "select * from student where name like '%?%' and sex = 0;"; PreparedStatement ps = connection.prepareStatement(sql); //ps.setString(1,"精"); ...
  • JDBC Java数据库连接

    2017-11-20 21:00:45
    JDBC(其实是一种jar包)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。即可以实现客户端与服务器端通信,执行数据库操作的一种技术         ...
  • 1.数据库三范式是什么 第一范式:每一列属性都是不可再分的属性值,确保每一列的原子性 第二范式:(确保表中每列都和主键相关)一张数据表至少有一个主键 第三范式:(确保每列都和主键列直接相关,而不是间接相关...
  • 模糊查询和分页实现的方法: 首先在工具类里面添加一个PageUtils类,把判断是否为空的类引入进来EmptyUtils; 然后在底层写分页和模糊查询的方法: //分页和模糊查询的整合 @Override public List&lt;User&...
  • 3.模糊查询 首先在src目录下新建一个properties文件,用于存储数据配置信息, 方便数据库信息后期变动,便于修改!! #配置连接数据库信息(动态生效) driverclass= com.mysql.jdbc.Driver url=jdbc:mysql://...
  • 数据库JDBC连接

    2011-08-18 10:45:51
    下面罗列了各种数据库使用JDBC连接的方式,可以作为一个手册使用。... 2 数据库连接池的应用。... 6 一、Tomcat配置数据源:... 15 二、Hibernate配置连接池有三种方法:... 17 一、Hibernate 连接池:C3P0 配置....
  • 作业15-JDBC数据库编程

    2021-06-30 06:21:18
    参考资料 本次作业参考文件MySQL操作视频 数据库相关jar文件请参考QQ群文件。 1. 本周学习总结 ...2.2 系统中使用到了JDBC中什么关键类? 2.3 截图数据库相关模块的关键代码。关键行需要加注释。 2.4...
  • mybatis

    千次阅读 2019-06-28 13:27:05
    1. 创建maven工程、添加开发依赖、创建数据库和表; 2. 创建domain实体类和dao mybatis是一门java语言编写持久层框架,大大简化了jdbc操作,省去了我们注册驱动,获取连接等细节操作。 org.mybatis mybatis...
  • java基础知识

    千次阅读 多人点赞 2019-07-31 19:21:46
    数据库操作(JDBC/增删改查/用结果集更新数据库/缓冲/预处理/事务处理/批处理/模糊查询/范围查询/复合查询/排序查询)。 模糊查询where name like ‘[张李]%’,% 0个或多个,_ 一个,排序查询Order by height, ...
  • JavaWeb

    千次阅读 多人点赞 2017-12-26 09:09:24
    304:查找本地资源 404:资源不存在 500:服务器内部错误 Servlet的生命周期: 第一次访问Servlet的时候,服务器就会创建一个Servlet对象,init方法就会执行。任何一次请求服务器就会创建一个Service方法。service...
  • 将“商品表.xls”和“类别表.xls”中的数据导入到数据库中,实现相关检索功能,以及模糊搜索功能。 以下程序涉及到内容: 1.从excel文件中导入数据到数据库。 2.分页功能 3.模糊搜索 咱们先说第一个内容:如何将...
  • JDBC数据库操作

    2017-05-17 14:54:42
    在学习之前我们首先了解一下什么是...简单来说JDBC提供给我们程序对数据库之间的桥梁,使我们的程序操作数据库变得简单。利用JDBC可以使我们方便的操作数据库。 使用JDBC的好处 有了JDBC,向各种关系数据发送SQL语句
  • sql模糊查找(利用jsp)

    千次阅读 2019-03-25 09:02:12
    jsp中利用sql的模糊查找 % 这个符号有三种用法 将它放在前面“%x” 这是查询数据库中你以 x 结尾的数据 将它放在后面“x%” 这是查询数据库中你以 x 开头的数据 将它放在两侧“%x%” 这是查询数据库中你的...
  • JDBC+Servlet+JSP实现简单的数据遍历和查找功能

    千次阅读 多人点赞 2017-11-05 22:26:23
    一、目标效果 ...两个输入框都能单一和配合查询,描述支持模糊查询。   可以直接跳到末尾查看动图效果 二、工作准备 1、涉及的知识点 JDBCJSPJSTLServletEL 2、jar 包准备 mysql-connec

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,638
精华内容 3,455
关键字:

数据库模糊查找jdbc