Skip to content

1 jdbc介绍

JDBC(Java DataBase Connectivity) 称为Java数据库连接,它是一种用于数据库访问的应用程序API,由一组用Java语言编写的类和接口组成,有了JDBC就可以用同一的语法对多种关系数据库进行访问,而不用担心其数据库操作语言的差异。 有了JDBC,就不必为访问Mysql数据库专门写一个程序,为访问Oracle又专门写一个程序等等。

2020-11-25_101206

2020-11-25_101219

1.1 JDBC优缺点

  • 优点:
    • JDBC使得编程人员从复杂的驱动器调用命令和函数中解脱出来,可以致力于应用程序中的关键地方。
    • JDBC支持不同的关系数据库,这使得程序的可移植性大大加强。
    • JDBC API是面向对象的,可以让用户把常用的方法封装为—个类,以备后用
  • 缺点:
    • 使用JDBC,访问数据记录的速度会受到一定程度的影响。
    • JDBC结构中包含不同厂家的产品,这就给更改数据源带来了很大的麻烦。

1.2 概述

JDBC核心接口与类

JDBC核心类库包含在java.sql包中。

    • DriverManager:负责管理JDBC驱动程序。使用JDBC驱动程序之前,必须先将驱动程序加载并注册后才可以使用,同时提供方法来建立与数据库的连接。
    • SQLException-有关数据库操作的异常
  • 接口:
    • Connection:特定数据库的连接(会话)。在连接上下文中执行SQL语句并返回结果。
    • PreparedStatement:表示预编译的 SQL 语句的对象。
    • Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。
    • ResultSet :表示数据库结果集的数据表,通常通过执行查询数据库的语句生成 。
    • CallableStatement :用于执行 SQL 存储过程的接口 。

1.3 创建JDBC应用程序的步骤

  • 载入JDBC驱动程序
  • 定义连接URL
  • 建立连接
  • 创建Statement对象
  • 执行查询或更新
  • 结果处理
  • 关闭连接

1.4 数据库驱动程序

数据库驱动程序分类

  • Type 1: jdbc-odbc桥

    • 把JDBC API调用转换成ODBC API 调用, 然后ODBC API调用针对供应商的ODBC 驱动程序来访问数据库, 即利用JDBC- ODBC 桥通过ODBC来存储数据源 。
  • Type 2: 本地API驱动

    • 本地api驱动直接把jdbc调用转变为数据库的标准调用再去访问数据库. 这种方法需要本地数据库驱动代码。讯。
  • Type 3: 网络协议驱动

    • 它使用一种与具体数据库无关的协议将数据库请求发送给一个中间服务器。
  • Type 4: 本地协议驱动

    • 这种驱动直接把jdbc调用转换为符合相关数据库系统规范的请求.由于4型驱动写的应用可以直接和数据库服务器通讯,这种类型的驱动完全由java实现,因此实现了平台独立性。 通常开发中多采用第四种方式,这种驱动不需要先把jdbc的调用传给odbc或本地数据库接口或者是中间层服务器,所以它的执行效率是非常高的驱动

    各数据库厂商均提供对 JDBC 的支持,即提供数据库连接使用的驱动程序文件需要为数据库应用程序正确加载驱动程序文件以获得数据库连接,实施操作

    Oracle 数据库的 JDBC 驱动程序文件 “ojdbc14.jar”(Oracle官方网站下载)

2 入门程序

2.1 jdbc数据库准备

sql
/*
SQLyog Ultimate v12.08 (64 bit)
MySQL - 5.7.18 : Database - jdbc_his
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`jdbc_his` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `jdbc_his`;

/*Table structure for table `user` */

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `displayname` varchar(50) DEFAULT NULL COMMENT '昵称',
  `password` varchar(100) NOT NULL COMMENT '密码',
  `birthday` date DEFAULT NULL COMMENT '出生日期',
  `gender` varchar(5) DEFAULT '1' COMMENT '性别 1男,2女',
  `telephone` varchar(20) DEFAULT NULL COMMENT '手机号',
  `email` varchar(100) DEFAULT NULL COMMENT '邮箱',
  `last_logintime` datetime DEFAULT NULL COMMENT '最后一次登录时间',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `valid` varchar(5) DEFAULT '1' COMMENT '有效状态1有效,0 无效',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert  into `user`(`id`,`username`,`displayname`,`password`,`birthday`,`gender`,`telephone`,`email`,`last_logintime`,`create_time`,`valid`) values (1,'admin','管理员','123456','2021-11-25','1','13888888888',NULL,NULL,'2021-11-25 11:38:30','1');


/*Data for the table `user` */

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

2.2 驱动

idea中下载驱动

2.3 idea中加载驱动

项目结构中选择【Modules】->[Dependencies]

2020-11-25_093857

选择[+]选择驱动所在的位置

2.4 常用的数据库连接字符串

Microsoft SQL Server

Microsoft SQL Server JDBC Driver (一般用来连接 SQLServer 2000)

**驱动程序包名:**msbase.jar mssqlserver.jar msutil.jar

驱动程序类名: com.microsoft.jdbc.sqlserver.SQLServerDriver

JDBC URL: jdbc:microsoft:sqlserver://<server_name>:<port>

默认端口1433,如果服务器使用默认端口则port可以省略

Microsoft SQL Server 2005 JDBC Driver

**驱动程序包名:**sqljdbc.jar

驱动程序类名: com.microsoft.sqlserver.jdbc.SQLServerDriver

JDBC URL: jdbc:sqlserver://<server_name>:<port>

默认端口1433,如果服务器使用默认端口则port可以省略

Oracle

Oracle Thin JDBC Driver

**驱动程序包名:**ojdbc14.jar

驱动程序类名: oracle.jdbc.driver.OracleDriver

JDBC URL:

jdbc:oracle:thin:@//<host>:<port>/ServiceName

jdbc:oracle:thin:@<host>:<port>:<SID>

IBM DB2

IBM DB2 Universal Driver Type 4

**驱动程序包名:**db2jcc.jar db2jcc_license_cu.jar

驱动程序类名: com.ibm.db2.jcc.DB2Driver

JDBC URL: jdbc:db2://<host>[:<port>]/<database_name>

IBM DB2 Universal Driver Type 2

**驱动程序包名:**db2jcc.jar db2jcc_license_cu.jar

驱动程序类名: com.ibm.db2.jcc.DB2Driver

JDBC URL: jdbc:db2:<database_name>

MySQL

MySQL Connector/J Driver

驱动程序包名:MySQL-connector-java-x.x.xx-bin.jar

驱动程序类名: com.mysql.jdbc.Driver

JDBC URL: jdbc:mysql://<host>:<port>/<database_name>

默认端口3306,如果服务器使用默认端口则port可以省略

MySQL Connector/J Driver 允许在URL中添加额外的连接属性jdbc:mysql://<host>:<port>/<database_name>?property1=value1&property2=value2

Informix

Informix JDBC Driver

**驱动程序包名:**ifxjdbc.jar

驱动程序类名: com.informix.jdbc.IfxDriver

JDBC URL: jdbc:informix-sqli://{<ip-address>|<host-name>}:<port-number>[/<dbname>]:INFORMIXSERVER=<server-name>

Sybase

Sybase Adaptive Server Enterprise JDBC Driver

**驱动程序包名:**jconn2.jar 或jconn3.jar

驱动程序类名: com.sybase.jdbc2.jdbc.SybDriver (com.sybase.jdbc3.jdbc.SybDriver)

JDBC URL: jdbc:sybase:Tds:<host>:<port>默认端口5000

Sybase Adaptive Server Anywhere or Sybase IQ JDBC Driver

**驱动程序包名:**jconn2.jar 或jconn3.jar

驱动程序类名: com.sybase.jdbc2.jdbc.SybDriver (com.sybase.jdbc3.jdbc.SybDriver)

JDBC URL: jdbc:sybase:Tds:<host>:<port>?ServiceName=<database_name>

默认端口2638

PostgreSQL

PostgreSQL Native JDBC Driver

驱动程序包名:驱动程序类名: org.postgresql.Driver

JDBC URL: jdbc:postgresql://<host>:<port>/<database_name>

默认端口5432

Teradata

Teradata Driver for the JDBC Interface

**驱动程序包名:**terajdbc4.jar tdgssjava.jar gui.jar

驱动程序类名: com.ncr.teradata.TeraDriver

JDBC URL: Type 4: jdbc:teradata://DatabaseServerName/Param1,Param2,...

Type 3: jdbc:teradata://GatewayServerName:PortNumber

/DatabaseServerName/Param1,Param2,...

Netezza

Netezza JDBC Driver

**驱动程序包名:**terajdbc4.jar tdgssjava.jar gui.jar

驱动程序类名: org.netezza.Driver

JDBC URL: jdbc:netezza://<host>:<port>/<database_name>

2.5 代码实现

java
package com.neuedu.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 项目:      jdbc
 * 类名:       JDBCTest1
 * 创建时间:  2020/11/25  9:31
 * 描述 :     JDBC入门程序
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class JDBCTest1 {

    public static final String driver = "com.mysql.jdbc.Driver";
    //连接的数据 mysql的默认端口 3306  Oracle 1521
    public static final String url = "jdbc:mysql://127.0.0.1:3306/jdbc_his";
    //连接数据库的用户名、密码
    public static final String username = "root";
    public static final String password = "root";


    /**
     * 1 加载启动,
     * 2 创建连接(定义url, 用户、密码) Connection
     * 3 创建 Statement ->
     * 4 执行Sql语句
     * 5    update\insert\delete  影响的行数
     *      select 结果集 解析ResultSet
     * 6  关闭资源
     *
     * @param args
     */
    public static void main(String[] args) {

        Connection conn = null;
        Statement stmt = null;
        try {
            //1 加载驱动
            Class.forName(driver);
//            2 创建连接(定义url, 用户、密码) Connection
            conn = DriverManager.getConnection(url,username,password);
            System.out.println(conn);

            //Statement
            stmt = conn.createStatement();


            //执行sql语句
            //update  update\delete\insert
            //query   select
            StringBuffer sql = new StringBuffer();
            sql.append( " INSERT INTO USER (		   ");
            sql.append( "   username,                  " );
            sql.append( "   displayname,               " );
            sql.append( "   password,                  " );
            sql.append( "   birthday,                  " );
            sql.append( "   telephone,                 " );
            sql.append( "   email                      " );
            sql.append( "                              " );
            sql.append( " )                            " );
            sql.append( " VALUES                       " );
            sql.append( "   (                          " );
            sql.append( "                              " );
            sql.append( "     'admin',                 " );
            sql.append( "     '管理员',                " );
            sql.append( "     '123456',                " );
            sql.append( "     '2020-11-25',            " );
            sql.append( "                              " );
            sql.append( "     '17745125669',           " );
            sql.append( "     'email@neusoft.com'      " );
            sql.append( "   )                          " );
            int count = stmt.executeUpdate(sql.toString());

            System.out.println("插入成功的条数\t"+count);

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

            if(stmt != null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

3 使用Statement执行语句

Statement接口提供可执行 SQL 命令的方法:

java
boolean execute(String sql) throws SQLException

ResultSet executeQuery(String sql) throws SQLException 

int executeUpdate(String sql) throws SQLException

3.1 执行插入语句

java
public void testInsert(){
        Connection conn = null;
        Statement stmt = null;
        try {
            //1 加载驱动
            Class.forName(driver);
//            2 创建连接(定义url, 用户、密码) Connection
            conn = DriverManager.getConnection(url,username,password);
            System.out.println(conn);

            //Statement
            stmt = conn.createStatement();


            //执行sql语句
            //update  update\delete\insert
            //query   select
            StringBuffer sql = new StringBuffer();
            sql.append( " INSERT INTO USER (		   ");
            sql.append( "   username,                  " );
            sql.append( "   displayname,               " );
            sql.append( "   password,                  " );
            sql.append( "   birthday,                  " );
            sql.append( "   telephone,                 " );
            sql.append( "   email                      " );
            sql.append( "                              " );
            sql.append( " )                            " );
            sql.append( " VALUES                       " );
            sql.append( "   (                          " );
            sql.append( "                              " );
            sql.append( "     'admin',                 " );
            sql.append( "     '管理员',                " );
            sql.append( "     '123456',                " );
            sql.append( "     '2020-11-25',            " );
            sql.append( "                              " );
            sql.append( "     '17745125669',           " );
            sql.append( "     'email@neusoft.com'      " );
            sql.append( "   )                          " );
            int count = stmt.executeUpdate(sql.toString());

            System.out.println("插入成功的条数\t"+count);

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

            if(stmt != null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

3.2 执行修改语句

java
public static void testUpdate() {
        Connection conn = null;
        Statement stmt = null;
        try {
            //1 加载驱动
            Class.forName(driver);
            // 2 创建连接(定义url, 用户、密码) Connection
            conn = DriverManager.getConnection(url, username, password);
            System.out.println(conn);

            //Statement
            stmt = conn.createStatement();


            //执行sql update 语句

            StringBuffer sql = new StringBuffer();
            sql.append(" UPDATE 							");
            sql.append("   user                             ");
            sql.append(" SET                                ");
            sql.append("   displayname = '系统管理员',      ");
            sql.append("   password = 'qwerfvcxzasd123456', ");
            sql.append("   birthday = '2020-01-02' ,        ");
            sql.append("   gender = '2',                    ");
            sql.append("   telephone = '13888888888',       ");
            sql.append("   email = 'update-mail@163.com'    ");
            sql.append(" WHERE id = 1                       ");

            int count = stmt.executeUpdate(sql.toString());

            System.out.println("更新成功的条数\t" + count);

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

            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

3.3 执行删除语句

3.4 执行查询语句

操作结果集元数据

java
//元数据
ResultSetMetaData meta = rs.getResultSetMetaData();
try {
    //查询结果列的总数
    int columnCount = meta.getColumnCount();
    //获取Label
    String labelName = meta.getColumnLabel(int index);
    //获取列的原始名字
    String columnName = meta.getColumnName(int index);
    //获取列的数据类型
    int type = meta.getColumnType(int column);
    

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

SQL类型对应Java数据类型

java.sql.Types

SQL TypeJava Type
CHARString
VARCHARString
LONGVARCHARString
NUMERICjava.math.BigDecimal
DECIMALjava.math.BigDecimal
BITboolean
TINYINTbyte
SMALLINTshort
INTEGERint
SQL TypeJava Type
BIGINTlong
REALfloat
FLOATdouble
DOUBLEdouble
BINARYbyte[]
VARBINARYbyte[]
LONGVARBINARYbyte[]
DATEjava.sql.Date
TIMEjava.sql.Time
TIMESTAMPjava.sql.Timestamp

操作结果集对象

  • ResultSet接口提供可对结果集进行操作的方法:
    • 移动结果集操作指针:
      • boolean next() throws SQLException
    • 指定数据类型根据传入列的名字获取指定列的值
      • Xxx getXxx(String columnName) throws SQLException
    • 指定数据类型根据传入列的编号获取指定列的值: 索引从1 开始
      • Xxx getXxx(1) throws SQLException

ResultSet接口的getXxx 方法

MethodJava Technology Type Returned
getASCIIStreamjava.io.InputStream
getBigDecimaljava.math.BigDecimal
getBinaryStreamjava.io.InputStream
getBooleanboolean
getBytebyte
getBytesbyte[ ]
getDatejava.sql.Date
getDoubledouble
getFloatfloat
MethodJava Technology Type Returned
getIntint
getLonglong
getObjectObject
getShortshort
getStringjava.lang.String
getTimejava.sql.Time
getTimestampjava.sql.Timestamp
getUnicodeStreamjava.io.InputStream of Unicode characters

JDBC日期时间处理

对于数据库种不同的时间类型,要分别采用与之相对应的Java包装类来存取:

  • 日期类型用java.sql.Date
  • 时间类型用java.sql.Time
  • 日期/时间类型用java.sql.Timestamp;
  • getTimestamp()可以把年月日时分秒都取出来,getDate()只能取出年月日,getTime()只能取出时分秒。 JDBC的日期/时间类型转换为字符串
  • Timestamp timeStamp = //通过数据库访问获取到该数据 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String str = sdf.format(timeStamp);
java
  public static void testSelect() {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //1 加载驱动
            Class.forName(driver);
            // 2 创建连接(定义url, 用户、密码) Connection
            conn = DriverManager.getConnection(url, username, password);
            System.out.println(conn);

            //Statement
            stmt = conn.createStatement();


            //执行sql update 语句

            String sql = "SELECT   id, username,  displayname,   password,  birthday, gender,  telephone, email, last_logintime,  create_time,  valid  FROM user\n";


            rs = stmt.executeQuery(sql);


            //解析元数据
            ResultSetMetaData meta = rs.getMetaData();
            int columnCount = meta.getColumnCount();
			//总列数
            System.out.println("columnCount\t"+columnCount);
            //遍历每个列的字段名字、类型名字
            for (int i = 1; i <= columnCount; i++) {
                String label = meta.getColumnLabel(i);
                String typeName = meta.getColumnTypeName(i);
                System.out.print(label+"("+typeName+")\t");
            }
            System.out.println();


            //解析结果集
            //id(INT)
            // username(VARCHAR)
            // displayname(VARCHAR)
            // password(VARCHAR)
            // birthday(DATE)
            // gender(VARCHAR)
            // telephone(VARCHAR)
            // email(VARCHAR)
            // last_logintime(DATETIME)
            // create_time(DATETIME)
            // valid(VARCHAR)
            while (rs.next()){
                int index = 1;
                int id = rs.getInt(index++);
                String userName = rs.getString(index++);
                String displayname = rs.getString(index++);
                String password = rs.getString(index++);
                Date birthday = rs.getDate(index++); //到年月日
                String gender = rs.getString(index++);
                String telephone = rs.getString(index++);
                String email = rs.getString(index++);

                Date lastLoginTime = rs.getTimestamp(index++); //年月日、时分秒
                Date createTime = rs.getTimestamp(index++); //年月日、时分秒

                String valid = rs.getString(index++);

                System.out.printf("id:%d\tuserName:%s\tdisplayname:%s\tpassword:%s\tbirthday:%s\tgender:%s\ttelephone:%s\temail:%s\tlastLoginTime:%s\tcreateTime:%s\tvalid:%s\r\n",
                        id,
                        userName,
                        displayname,
                        password,
                        birthday.toString(),
                        gender,
                        telephone,
                        email,
                        lastLoginTime== null?"":lastLoginTime.toString(),
                        createTime ==null? "": createTime.toString(),
                        valid
                        );

            }



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

            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

4 PreparedStatement

PreparedStatement接口 PreparedStatement接口是Statement接口的子接口,允许使用不同的参数多次执行同样的 SQL 语句。 Connection接口提供创建PreparedStatement对象的方法,可指定SQL语句:

4.1 sql注入的解决

sql注入

java
/**
     * 根据用户名查询用户 有sql注入的问题
     * @param loginUser
     */
    public static void testSelect2(String loginUser) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //1 加载驱动
            Class.forName(driver);
            // 2 创建连接(定义url, 用户、密码) Connection
            conn = DriverManager.getConnection(url, username, password);
            System.out.println(conn);

            //Statement
            stmt = conn.createStatement();


            //执行sql update 语句

            String sql = "SELECT   id, username,  displayname,   password,  " +
                    "birthday, gender,  telephone, email, last_logintime,  create_time,  valid  FROM user " +
                    "where username= '"+loginUser+"'";

            System.out.println("sql\r\n"+sql);

            rs = stmt.executeQuery(sql);


            //解析元数据
            ResultSetMetaData meta = rs.getMetaData();
            int columnCount = meta.getColumnCount();

            System.out.println("columnCount\t"+columnCount);
            for (int i = 1; i <= columnCount; i++) {
                String label = meta.getColumnLabel(i);
                String typeName = meta.getColumnTypeName(i);
                System.out.print(label+"("+typeName+")\t");
            }
            System.out.println();


            //解析结果集
            //id(INT)
            // username(VARCHAR)
            // displayname(VARCHAR)
            // password(VARCHAR)

            // birthday(DATE)
            // gender(VARCHAR)
            // telephone(VARCHAR)
            // email(VARCHAR)


            // last_logintime(DATETIME)
            // create_time(DATETIME)
            // valid(VARCHAR)
            while (rs.next()){
                int index = 1;
                int id = rs.getInt(index++);
                String userName = rs.getString(index++);
                String displayname = rs.getString(index++);
                String password = rs.getString(index++);
                Date birthday = rs.getDate(index++); //到年月日
                String gender = rs.getString(index++);
                String telephone = rs.getString(index++);
                String email = rs.getString(index++);

                Date lastLoginTime = rs.getTimestamp(index++); //年月日、时分秒
                Date createTime = rs.getTimestamp(index++); //年月日、时分秒

                String valid = rs.getString(index++);

                System.out.printf("id:%d\tuserName:%s\tdisplayname:%s\tpassword:%s\tbirthday:%s\tgender:%s\ttelephone:%s\temail:%s\tlastLoginTime:%s\tcreateTime:%s\tvalid:%s\r\n",
                        id,
                        userName,
                        displayname,
                        password,
                        birthday.toString(),
                        gender,
                        telephone,
                        email,
                        lastLoginTime== null?"":lastLoginTime.toString(),
                        createTime ==null? "": createTime.toString(),
                        valid
                );

            }



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

            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

使用PreparedStatement执行预编译的sql,解决注入的问题

java
 public static void testSelect(String loginUser) {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            //1 加载驱动
            Class.forName(driver);
            // 2 创建连接(定义url, 用户、密码) Connection
            conn = DriverManager.getConnection(url, username, password);
            System.out.println(conn);

            //执行sql update 语句
            String sql = "SELECT   id, username,  displayname,   password,  birthday, gender,  telephone, email, last_logintime,  create_time,  valid  FROM user\n" +
                    "where username = ? ";

            stmt =conn.prepareStatement(sql);

            stmt.setString(1,loginUser);
            rs = stmt.executeQuery();

            while (rs.next()){
                int index = 1;
                int id = rs.getInt(index++);
                String userName = rs.getString(index++);
                String displayname = rs.getString(index++);
                String password = rs.getString(index++);
                Date birthday = rs.getDate(index++); //到年月日
                String gender = rs.getString(index++);
                String telephone = rs.getString(index++);
                String email = rs.getString(index++);

                Date lastLoginTime = rs.getTimestamp(index++); //年月日、时分秒
                Date createTime = rs.getTimestamp(index++); //年月日、时分秒

                String valid = rs.getString(index++);

                System.out.printf("id:%d\tuserName:%s\tdisplayname:%s\tpassword:%s\tbirthday:%s\tgender:%s\ttelephone:%s\temail:%s\tlastLoginTime:%s\tcreateTime:%s\tvalid:%s\r\n",
                        id,
                        userName,
                        displayname,
                        password,
                        birthday.toString(),
                        gender,
                        telephone,
                        email,
                        lastLoginTime== null?"":lastLoginTime.toString(),
                        createTime ==null? "": createTime.toString(),
                        valid
                );

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

            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

4.2 解决批量执行sql

java
package com.neuedu.jdbc;

import java.util.Date;

/**
 * 项目:      jdbc
 * 类名:       User
 * 创建时间:  2020/11/25  14:40
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io 实体类
 */
public class User {
    private Integer id;
    private String username;
    private String displayname;
    private String password;
    private Date birthday;
    private String gender;
    private String telephone;
    private String email;
    private Date last_logintime;
    private Date create_time;
    private String valid;

    public User() {
    }

    public User(Integer id, String username, String displayname, String password, Date birthday, String gender, String telephone, String email, Date last_logintime, Date create_time, String valid) {
        this.id = id;
        this.username = username;
        this.displayname = displayname;
        this.password = password;
        this.birthday = birthday;
        this.gender = gender;
        this.telephone = telephone;
        this.email = email;
        this.last_logintime = last_logintime;
        this.create_time = create_time;
        this.valid = valid;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getDisplayname() {
        return displayname;
    }

    public void setDisplayname(String displayname) {
        this.displayname = displayname;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Date getLast_logintime() {
        return last_logintime;
    }

    public void setLast_logintime(Date last_logintime) {
        this.last_logintime = last_logintime;
    }

    public Date getCreate_time() {
        return create_time;
    }

    public void setCreate_time(Date create_time) {
        this.create_time = create_time;
    }

    public String getValid() {
        return valid;
    }

    public void setValid(String valid) {
        this.valid = valid;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", displayname='" + displayname + '\'' +
                ", password='" + password + '\'' +
                ", birthday=" + birthday +
                ", gender='" + gender + '\'' +
                ", telephone='" + telephone + '\'' +
                ", email='" + email + '\'' +
                ", last_logintime=" + last_logintime +
                ", create_time=" + create_time +
                ", valid='" + valid + '\'' +
                '}';
    }
}
java
package com.neuedu.jdbc;

import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 项目:      jdbc
 * 类名:       JDBCTest1
 * 创建时间:  2020/11/25  9:31
 * 描述 :     JDBC入门程序
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class JDBCTest2 {

    public static final String driver = "com.mysql.jdbc.Driver";
    //连接的数据 mysql的默认端口 3306  Oracle 1521
    public static final String url = "jdbc:mysql://127.0.0.1:3306/jdbc_his?useSSL=false";
    //连接数据库的用户名、密码
    public static final String username = "root";
    public static final String password = "root";


    /**
     * 1 加载启动,
     * 2 创建连接(定义url, 用户、密码) Connection
     * 3 创建 Statement ->
     * 4 执行Sql语句
     * 5    update\insert\delete  影响的行数
     * select 结果集 解析ResultSet
     * 6  关闭资源
     *
     * @param args
     */
    public static void main(String[] args) {



        List<User> list =  new ArrayList();
        list.add(new User(null,"abc","displayname","password",new Date(),"1","","",null,null,null));
        list.add(new User(null,"abc1","displayname","password",new Date(),"1","","",null,null,null));
        list.add(new User(null,"abc2","displayname","password",new Date(),"1","","",null,null,null));
        list.add(new User(null,"abc3","displayname","password",new Date(),"1","","",null,null,null));

        testInsertBatch(list);

    }

    /**
     * 批量插入
     * @param list
     */
    private static void testInsertBatch(List<User> list) {

        Connection con = null;
        PreparedStatement stmt = null;
        try {
            Class.forName(driver);
            con = DriverManager.getConnection(url, username, password);


            StringBuffer sql = new StringBuffer();
            sql.append(" INSERT INTO USER (		   ");
            sql.append("   username,                  ");
            sql.append("   displayname,               ");
            sql.append("   password,                  ");
            sql.append("   birthday,                  ");
            sql.append("   telephone,                 ");
            sql.append("   email     )                            ");
            sql.append(" VALUES                       ");
            sql.append("   (  ? ,   ? ,   ? ,   ? ,   ? ,   ?    )  ");
            stmt = con.prepareStatement(sql.toString());


            for (User user : list) {
                stmt.setString(1,  user.getUsername());
                stmt.setString(2,  user.getUsername());
                stmt.setString(3,  user.getUsername());
                stmt.setDate(4,  new java.sql.Date(user.getBirthday().getTime()));
                stmt.setString(5,  user.getUsername());
                stmt.setString(6,  user.getUsername());
                int count = stmt.executeUpdate();
                System.out.println("count:\t"+count);
            }

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

            if(stmt != null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(con != null){
                try {
                    con.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }


    }

}

5.Statement和PreparedStatement对比

6 事务管理

sql
CREATE DATABASE /*!32312 IF NOT EXISTS*/`jdbc_his` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `jdbc_his`;

/*Table structure for table `account` */

DROP TABLE IF EXISTS `account`;

CREATE TABLE `account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `account_name` varchar(50) DEFAULT NULL,
  `amout` decimal(10,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

/*Data for the table `account` */

insert  into `account`(`id`,`account_name`,`amout`) values (1,'张三','50.00'),(2,'李四','50.00');

6.1 事务实现

事务的概念,参考百度百科

java
package com.neuedu.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 项目:      jdbc
 * 类名:       MyAccount
 * 创建时间:  2020/11/25  15:30
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class MyAccount {


    public static final String driver = "com.mysql.jdbc.Driver";
    //连接的数据 mysql的默认端口 3306  Oracle 1521
    public static final String url = "jdbc:mysql://127.0.0.1:3306/jdbc_his?useSSL=false";
    //连接数据库的用户名、密码
    public static final String username = "root";
    public static final String password = "root";


    public void transfer(){
        {
            Connection conn = null;
            Statement stmt = null;
            try {
                //1 加载驱动
                Class.forName(driver);
                // 2 创建连接(定义url, 用户、密码) Connection
                conn = DriverManager.getConnection(url, username, password);
                conn.setAutoCommit(false);
                //Statement
                stmt = conn.createStatement();

                //执行sql update 语句
                String sql1 = "UPDATE  account SET amout = amout -50 WHERE id = 1";
                int count = stmt.executeUpdate(sql1); //立即的数据持久到数据库中



//                //清单柜面存款
//                int result = 0/0;


                String sql2 = "UPDATE  account SET amout = amout +50 WHERE id = 2";
                count += stmt.executeUpdate(sql2);

                System.out.println("更新成功的条数\t" + count);


                //提交
                conn.commit(); //手动提交
            } catch (Exception e) {
                try {
                    conn.rollback();
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
                e.printStackTrace();
            } finally {

                if (stmt != null) {
                    try {
                        stmt.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if (conn != null) {
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }

    public static void main(String[] args) {
        new MyAccount().transfer();
    }

}

7.Dao封装

java
package com.neuedu.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;

/**
 * 项目:      jdbc
 * 类名:       BaseDao
 * 创建时间:  2020/11/25  16:04
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public abstract  class BaseDao<T> {

    public static final String driver = "com.mysql.jdbc.Driver";
    //连接的数据 mysql的默认端口 3306  Oracle 1521
    public static final String url = "jdbc:mysql://127.0.0.1:3306/jdbc_his?useSSL=false";
    //连接数据库的用户名、密码
    public static final String username = "root";
    public static final String password = "root";


    /**
     * 加载链接
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    protected Connection getConnection() throws ClassNotFoundException, SQLException {
        Class.forName(driver);
        Connection conn = DriverManager.getConnection(url, username, password);
        return conn;
    }


    //1 列表 List
    public abstract List<T> list();

    //2 根据主键查询
    public abstract T getOne(int id);

    //3 查询总条数
    public abstract int count();

    //3根据主键更新
    public abstract boolean update(T t);

    //4 保存一条数据
    public abstract boolean save(T t);

    //5 根据主键删除一条
    public abstract boolean deleteOne(int id);

}
java
package com.neuedu.dao;

import com.neuedu.entity.User;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 项目:      jdbc
 * 类名:       UserDao
 * 创建时间:  2020/11/25  16:16
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class UserDao extends BaseDao<User> {
    @Override
    public List<User> list() {
        List<User> userList =  new ArrayList();
        String sql ="SELECT   id, username,  displayname,   password,  birthday, gender,  telephone, email, last_logintime,  create_time,  valid  FROM user " ;
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql);

            ResultSet rs = stmt.executeQuery();
            while (rs.next()){

                userList.add(new User(
                        rs.getInt("id"),
                        rs.getString("username"),
                        rs.getString("displayname"),
                        rs.getString("password"),
                        rs.getDate("birthday"),
                        rs.getString("gender"),
                        rs.getString("telephone"),
                        rs.getString("email"),
                        rs.getTimestamp("last_logintime"),
                        rs.getTimestamp("create_time"),
                        rs.getString("valid")
                ));
            }


            return userList;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    @Override
    public User getOne(int id) {
        User user = null;
        String sql ="SELECT   id, username,  displayname,   password,  birthday, gender,  telephone, email, last_logintime,  create_time,  valid  FROM user  where id = ? " ;
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql);

            stmt.setInt(1,id);
            ResultSet rs = stmt.executeQuery();
            if (rs.next()){
                user = new User(
                        rs.getInt("id"),
                        rs.getString("username"),
                        rs.getString("displayname"),
                        rs.getString("password"),
                        rs.getDate("birthday"),
                        rs.getString("gender"),
                        rs.getString("telephone"),
                        rs.getString("email"),
                        rs.getTimestamp("last_logintime"),
                        rs.getTimestamp("create_time"),
                        rs.getString("valid")
                );
            }



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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return user;
    }

    @Override
    public int count() {
        int count = 0;
        String sql ="SELECT  count(1)  FROM user " ;
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql);


            ResultSet rs = stmt.executeQuery();
            rs.next();
            count = rs.getInt(1);

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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return count;
    }

    @Override
    public boolean update(User user) {


        StringBuffer sql = new StringBuffer();
        sql.append(" UPDATE 							");
        sql.append("   user                             ");
        sql.append(" SET                                ");
        sql.append("   displayname =  ? ,      ");
        sql.append("   password = ? , ");
        sql.append("   birthday = ?  ,        ");
        sql.append("   gender = ?,                    ");
        sql.append("   telephone = ?,       ");
        sql.append("   email = ? ,  ");
        sql.append("   last_logintime = ? ,  ");
        sql.append("   valid = ?  ");
        sql.append(" WHERE id =  ?                       ");


        Connection conn = null;
        PreparedStatement stmt = null;
        int count = 0;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql.toString());

            int index = 0;
            stmt.setString(++index,user.getDisplayname());
            stmt.setString(++index,user.getPassword());
            stmt.setDate(++index, user.getBirthday()==null?null:new java.sql.Date(user.getBirthday().getTime()));
            stmt.setString(++index,user.getGender());
            stmt.setString(++index,user.getTelephone());
            stmt.setString(++index,user.getEmail());
            stmt.setTimestamp(++index,user.getLast_logintime()==null?null: new java.sql.Timestamp(user.getLast_logintime().getTime()));
            stmt.setString(++index,user.getValid());
            stmt.setInt(++index,user.getId());


            count = stmt.executeUpdate();



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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return count>0;
    }

    @Override
    public boolean save(User user) {


        StringBuffer sql = new StringBuffer();
        sql.append(" INSERT INTO USER (		   ");
        sql.append("   username,                  ");
        sql.append("   displayname,               ");
        sql.append("   password,                  ");
        sql.append("   birthday,                  ");
        sql.append("   gender,                  ");
        sql.append("   telephone,                 ");
        sql.append("   email     )                            ");
        sql.append(" VALUES                       ");
        sql.append("   (  ?,?,?,?,?,? ,? )     ");


        Connection conn = null;
        PreparedStatement stmt = null;
        int count = 0;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql.toString());

            int index = 0;
            stmt.setString(++index,user.getUsername());
            stmt.setString(++index,user.getDisplayname());
            stmt.setString(++index,user.getPassword());
            stmt.setDate(++index, user.getBirthday()==null?null:new java.sql.Date(user.getBirthday().getTime()));
            stmt.setString(++index,user.getGender());
            stmt.setString(++index,user.getTelephone());
            stmt.setString(++index,user.getEmail());



            count = stmt.executeUpdate();

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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return count>0;
    }

    @Override
    public boolean deleteOne(int id) {
        String sql = "delete from user where id = ?";

        Connection conn = null;
        PreparedStatement stmt = null;
        int count = 0;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql.toString());

            stmt.setInt(1 ,id);

            count = stmt.executeUpdate();

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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return count>0;
    }
}
  • 测试类
java
package com.neuedu.dao;

import com.neuedu.entity.User;

import java.util.Date;
import java.util.List;

/**
 * 项目:      jdbc
 * 类名:       UserDaoTest
 * 创建时间:  2020/11/25  16:22
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class UserDaoTest {
    public static void main(String[] args) {
        UserDao dao = new UserDao();

        System.out.println("+======================list ==============================");
        List<User> list = dao.list();
        for (User user : list) {
            System.out.println(user);
        }

        System.out.println("+======================getOne==============================");
        int id = 2;
        User user = dao.getOne(id);
        System.out.println(user);


        System.out.println("+======================count==============================");

        int count = dao.count();
        System.out.println("count\t"+count);


        System.out.println("+======================update==============================");
        user.setDisplayname(user.getDisplayname()+"--update");
        boolean success = dao.update(user);
        System.out.println("update success :\t"+success );


        System.out.println("+======================save==============================");
        User saveUser = new User(null,"Dao","displaynameDao","password",new Date(),"1","","",null,null,null);
        success = dao.save(saveUser);
        System.out.println("save success :\t"+success );

        System.out.println("+======================delete==============================");
        id = 5;
        success = dao.deleteOne(id);
        System.out.println("delete success :\t"+success );

    }
}

8.工具类封装

数据库脚本

sql
CREATE TABLE `account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `account_name` varchar(50) DEFAULT NULL,
  `amout` decimal(10,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

/*Data for the table `account` */

insert  into `account`(`id`,`account_name`,`amout`) values (1,'张三','50.00'),(2,'王五','50.00');

/*Table structure for table `user` */

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `displayname` varchar(50) DEFAULT NULL COMMENT '昵称',
  `password` varchar(100) NOT NULL COMMENT '密码',
  `birthday` date DEFAULT NULL COMMENT '出生日期',
  `gender` varchar(5) DEFAULT '1' COMMENT '性别 1男,2女',
  `telephone` varchar(20) DEFAULT NULL COMMENT '手机号',
  `email` varchar(100) DEFAULT NULL COMMENT '邮箱',
  `last_logintime` datetime DEFAULT NULL COMMENT '最后一次登录时间',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `valid` varchar(5) DEFAULT '1' COMMENT '有效状态1有效,0 无效',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

/*Data for the table `user` */

insert  into `user`(`id`,`username`,`displayname`,`password`,`birthday`,`gender`,`telephone`,`email`,`last_logintime`,`create_time`,`valid`) values (1,'admin','系统管理员','qwerfvcxzasd123456','2020-01-02','2','13888888888','update-mail@163.com',NULL,'2020-11-25 09:52:19','1'),(2,'abc','abc--update--update--update--update','abc','2020-11-25','1','abc','abc',NULL,'2020-11-25 14:53:53','1'),(3,'abc1','abc1','abc1','2020-11-25','1','abc1','abc1',NULL,'2020-11-25 14:53:53','1'),(4,'abc2','abc2','abc2','2020-11-25','1','abc2','abc2',NULL,'2020-11-25 14:53:53','1'),(6,'Dao','displaynameDao','password','2020-11-25','1','','',NULL,'2020-11-25 16:38:55','1'),(7,'Dao','displaynameDao','password','2020-11-25','1','','',NULL,'2020-11-25 16:40:51','1'),(8,'qwer','displayname','password','2020-11-26','1','13888888888','displayname@email.com',NULL,'2020-11-26 15:34:24','1');

8.1 Dao原始封装两张表的操作

8.1.1 实体类

java
package com.neuedu.entity;

import java.util.Date;

/**
 * 项目:      jdbc
 * 类名:       User
 * 创建时间:  2020/11/25  14:40
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io 实体类
 */
public class User {
    private Integer id;
    private String username;
    private String displayname;
    private String password;
    private Date birthday;
    private String gender;
    private String telephone;
    private String email;
    private Date last_logintime;
    private Date create_time;
    private String valid;

    public User() {
    }

    public User(Integer id, String username, String displayname, String password, Date birthday, String gender, String telephone, String email, Date last_logintime, Date create_time, String valid) {
        this.id = id;
        this.username = username;
        this.displayname = displayname;
        this.password = password;
        this.birthday = birthday;
        this.gender = gender;
        this.telephone = telephone;
        this.email = email;
        this.last_logintime = last_logintime;
        this.create_time = create_time;
        this.valid = valid;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getDisplayname() {
        return displayname;
    }

    public void setDisplayname(String displayname) {
        this.displayname = displayname;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Date getLast_logintime() {
        return last_logintime;
    }

    public void setLast_logintime(Date last_logintime) {
        this.last_logintime = last_logintime;
    }

    public Date getCreate_time() {
        return create_time;
    }

    public void setCreate_time(Date create_time) {
        this.create_time = create_time;
    }

    public String getValid() {
        return valid;
    }

    public void setValid(String valid) {
        this.valid = valid;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", displayname='" + displayname + '\'' +
                ", password='" + password + '\'' +
                ", birthday=" + birthday +
                ", gender='" + gender + '\'' +
                ", telephone='" + telephone + '\'' +
                ", email='" + email + '\'' +
                ", last_logintime=" + last_logintime +
                ", create_time=" + create_time +
                ", valid='" + valid + '\'' +
                '}';
    }
}





package com.neuedu.entity;

import java.math.BigDecimal;

/**
 * 项目:      jdbc
 * 类名:       Account
 * 创建时间:  2020/11/26  13:39
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class Account {


    private Integer id;
    private String account_name;
    private BigDecimal amout;


    public Account() {
    }

    public Account(Integer id, String account_name, BigDecimal amout) {
        this.id = id;
        this.account_name = account_name;
        this.amout = amout;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getAccount_name() {
        return account_name;
    }

    public void setAccount_name(String account_name) {
        this.account_name = account_name;
    }

    public BigDecimal getAmout() {
        return amout;
    }

    public void setAmout(BigDecimal amout) {
        this.amout = amout;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", account_name='" + account_name + '\'' +
                ", amout=" + amout +
                '}';
    }
}

8.1.2 BaseDao类

java
package com.neuedu.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;

/**
 * 项目:      jdbc
 * 类名:       BaseDao
 * 创建时间:  2020/11/25  16:04
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public abstract  class BaseDao<T> {

    public static final String driver = "com.mysql.jdbc.Driver";
    //连接的数据 mysql的默认端口 3306  Oracle 1521
    public static final String url = "jdbc:mysql://127.0.0.1:3306/jdbc_his?characterEncoding=utf8&useUnicode=true&useSSL=false";
    //连接数据库的用户名、密码
    public static final String username = "root";
    public static final String password = "root";


    /**
     * 加载链接
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    protected Connection getConnection() throws ClassNotFoundException, SQLException {
        Class.forName(driver);
        Connection conn = DriverManager.getConnection(url, username, password);
        return conn;
    }


    //1 列表 List
    public abstract List<T> list();

    //2 根据主键查询
    public abstract T getOne(int id);

    //3 查询总条数
    public abstract int count();

    //3根据主键更新
    public abstract boolean update(T t);

    //4 保存一条数据
    public abstract boolean save(T t);

    //5 根据主键删除一条
    public abstract boolean deleteOne(int id);


}

8.1.3 封装好的Dao类

java
package com.neuedu.dao;

import com.neuedu.entity.User;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 项目:      jdbc
 * 类名:       UserDao
 * 创建时间:  2020/11/25  16:16
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class UserDao extends BaseDao<User> {
    @Override
    public List<User> list() {
        List<User> userList =  new ArrayList();
        String sql ="SELECT   id, username,  displayname,   password,  birthday, gender,  telephone, email, last_logintime,  create_time,  valid  FROM user " ;
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql);

            ResultSet rs = stmt.executeQuery();
            while (rs.next()){

                userList.add(new User(
                        rs.getInt("id"),
                        rs.getString("username"),
                        rs.getString("displayname"),
                        rs.getString("password"),
                        rs.getDate("birthday"),
                        rs.getString("gender"),
                        rs.getString("telephone"),
                        rs.getString("email"),
                        rs.getTimestamp("last_logintime"),
                        rs.getTimestamp("create_time"),
                        rs.getString("valid")
                ));
            }


            return userList;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    @Override
    public User getOne(int id) {
        User user = null;
        String sql ="SELECT   id, username,  displayname,   password,  birthday, gender,  telephone, email, last_logintime,  create_time,  valid  FROM user  where id = ? " ;
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql);

            stmt.setInt(1,id);
            ResultSet rs = stmt.executeQuery();
            if (rs.next()){
                user = new User(
                        rs.getInt("id"),
                        rs.getString("username"),
                        rs.getString("displayname"),
                        rs.getString("password"),
                        rs.getDate("birthday"),
                        rs.getString("gender"),
                        rs.getString("telephone"),
                        rs.getString("email"),
                        rs.getTimestamp("last_logintime"),
                        rs.getTimestamp("create_time"),
                        rs.getString("valid")
                );
            }



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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return user;
    }

    @Override
    public int count() {
        int count = 0;
        String sql ="SELECT  count(1)  FROM user " ;
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql);


            ResultSet rs = stmt.executeQuery();
            rs.next();
            count = rs.getInt(1);

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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return count;
    }

    @Override
    public boolean update(User user) {


        StringBuffer sql = new StringBuffer();
        sql.append(" UPDATE 							");
        sql.append("   user                             ");
        sql.append(" SET                                ");
        sql.append("   displayname =  ? ,      ");
        sql.append("   password = ? , ");
        sql.append("   birthday = ?  ,        ");
        sql.append("   gender = ?,                    ");
        sql.append("   telephone = ?,       ");
        sql.append("   email = ? ,  ");
        sql.append("   last_logintime = ? ,  ");
        sql.append("   valid = ?  ");
        sql.append(" WHERE id =  ?                       ");


        Connection conn = null;
        PreparedStatement stmt = null;
        int count = 0;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql.toString());

            int index = 0;
            stmt.setString(++index,user.getDisplayname());
            stmt.setString(++index,user.getPassword());
            stmt.setDate(++index, user.getBirthday()==null?null:new java.sql.Date(user.getBirthday().getTime()));
            stmt.setString(++index,user.getGender());
            stmt.setString(++index,user.getTelephone());
            stmt.setString(++index,user.getEmail());
            stmt.setTimestamp(++index,user.getLast_logintime()==null?null: new java.sql.Timestamp(user.getLast_logintime().getTime()));
            stmt.setString(++index,user.getValid());
            stmt.setInt(++index,user.getId());


            count = stmt.executeUpdate();



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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return count>0;
    }

    @Override
    public boolean save(User user) {


        StringBuffer sql = new StringBuffer();
        sql.append(" INSERT INTO USER (		   ");
        sql.append("   username,                  ");
        sql.append("   displayname,               ");
        sql.append("   password,                  ");
        sql.append("   birthday,                  ");
        sql.append("   gender,                  ");
        sql.append("   telephone,                 ");
        sql.append("   email     )                            ");
        sql.append(" VALUES                       ");
        sql.append("   (  ?,?,?,?,?,? ,? )     ");


        Connection conn = null;
        PreparedStatement stmt = null;
        int count = 0;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql.toString());

            int index = 0;
            stmt.setString(++index,user.getUsername());
            stmt.setString(++index,user.getDisplayname());
            stmt.setString(++index,user.getPassword());
            stmt.setDate(++index, user.getBirthday()==null?null:new java.sql.Date(user.getBirthday().getTime()));
            stmt.setString(++index,user.getGender());
            stmt.setString(++index,user.getTelephone());
            stmt.setString(++index,user.getEmail());



            count = stmt.executeUpdate();

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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return count>0;
    }

    @Override
    public boolean deleteOne(int id) {
        String sql = "delete from user where id = ?";

        Connection conn = null;
        PreparedStatement stmt = null;
        int count = 0;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql.toString());

            stmt.setInt(1 ,id);

            count = stmt.executeUpdate();

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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return count>0;
    }
}







package com.neuedu.dao;

import com.neuedu.entity.Account;
import com.neuedu.entity.User;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 项目:      jdbc
 * 类名:       AccountDao
 * 创建时间:  2020/11/26  13:38
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class AccountDao extends BaseDao<Account> {
    @Override
    public List<Account> list() {
        List<Account> list =  new ArrayList();
        String sql ="SELECT * FROM account " ;
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql);

            ResultSet rs = stmt.executeQuery();
            while (rs.next()){

                list.add(new Account(
                        rs.getInt("id"),
                        rs.getString("account_name"),
                        rs.getBigDecimal("amout")
                ));
            }

            return list;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }



    @Override
    public Account getOne(int id) {
        Account account = null;
        String sql ="SELECT * FROM account   where id = ? " ;
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql);

            stmt.setInt(1,id);
            ResultSet rs = stmt.executeQuery();
            if (rs.next()){
                account = new Account(
                        rs.getInt("id"),
                        rs.getString("account_name"),
                        rs.getBigDecimal("amout")
                );
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return account;
    }

    @Override
    public int count() {
        int count = 0;
        String sql ="SELECT  count(1)  FROM account " ;
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql);


            ResultSet rs = stmt.executeQuery();
            rs.next();
            count = rs.getInt(1);

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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return count;
    }

    @Override
    public boolean update(Account account) {


        StringBuffer sql = new StringBuffer();
        sql.append(" UPDATE 							");
        sql.append("   account                      ");
        sql.append(" SET                                ");
        sql.append("   account_name =  ? ,      ");
        sql.append("   amout = ?  ");
        sql.append(" WHERE id =  ?                       ");


        Connection conn = null;
        PreparedStatement stmt = null;
        int count = 0;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql.toString());

            int index = 0;
            stmt.setString(++index,account.getAccount_name());
            stmt.setBigDecimal(++index,account.getAmout());

            stmt.setInt(++index,account.getId());


            count = stmt.executeUpdate();



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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return count>0;
    }

    @Override
    public boolean save(Account account) {


        StringBuffer sql = new StringBuffer();
        sql.append(" INSERT INTO account (  account_name,     amout )   VALUES      (  ?,? )     ");


        Connection conn = null;
        PreparedStatement stmt = null;
        int count = 0;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql.toString());

            int index = 0;
            stmt.setString(++index,account.getAccount_name());
            stmt.setBigDecimal(++index,account.getAmout());

            count = stmt.executeUpdate();

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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return count>0;
    }

    @Override
    public boolean deleteOne(int id) {
        String sql = "delete from account where id = ?";

        Connection conn = null;
        PreparedStatement stmt = null;
        int count = 0;
        try {
            conn = super.getConnection();
            stmt = conn.prepareStatement(sql.toString());

            stmt.setInt(1 ,id);

            count = stmt.executeUpdate();

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

            if(stmt != null ){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null ){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return count>0;
    }
}

8.1.4 测试类

java
package com.neuedu.dao;

import com.neuedu.entity.Account;
import com.neuedu.entity.User;

import java.util.Date;
import java.util.List;

/**
 * 项目:      jdbc
 * 类名:       UserDaoTest
 * 创建时间:  2020/11/25  16:22
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class AccountDaoTest {
    public static void main(String[] args) {
        AccountDao dao = new AccountDao();

        System.out.println("+======================list ==============================");
        List<Account> list = dao.list();
        for (Account account : list) {
            System.out.println(account);
        }

        System.out.println("+======================getOne==============================");
        int id = 2;
        Account account = dao.getOne(id);
        System.out.println(account);


        System.out.println("+======================count==============================");

        int count = dao.count();
        System.out.println("count\t"+count);


        System.out.println("+======================update==============================");
        account.setAccount_name("王五");
        boolean success = dao.update(account);
        System.out.println("update success :\t"+success );


//        System.out.println("+======================save==============================");
//        Account saveAccount = new Account(null,"项目经理",60.0);
//        success = dao.save(saveAccount);
//        System.out.println("save success :\t"+success );

        System.out.println("+======================delete==============================");
        id = 3;
        success = dao.deleteOne(id);
        System.out.println("delete success :\t"+success );

    }
}

8.2 公共类操作封装

8.2.1结果集映射类

java
package com.neuedu.util;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 项目:      jdbc
 * 类名:       RowMap
 * 创建时间:  2020/11/26  13:59
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
@FunctionalInterface
public interface RowMap<U> {

   U rowmap(ResultSet rs) throws SQLException;

}

8.2.2 工具类

java
package com.neuedu.util;

import com.neuedu.entity.User;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 项目:      jdbc
 * 类名:       JDBCUtil
 * 创建时间:  2020/11/26  13:55
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class JDBCUtil {


    public static final String driver = "com.mysql.jdbc.Driver";
    //连接的数据 mysql的默认端口 3306  Oracle 1521
    public static final String url = "jdbc:mysql://127.0.0.1:3306/jdbc_his?characterEncoding=utf8&useUnicode=true&useSSL=false";
    //连接数据库的用户名、密码
    public static final String username = "root";
    public static final String password = "root";


    static {
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    /**
     * 加载数据库连接
     *
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    private static Connection getConnection() throws ClassNotFoundException, SQLException {

        Connection conn = DriverManager.getConnection(url, username, password);
        return conn;
    }


    private static void close(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    private static void close(PreparedStatement stmt) {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    private static void close(ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    private static void close(ResultSet rs, PreparedStatement stmt, Connection conn) {
        close(rs);
        close(stmt);
        close(conn);
    }

    /**
     * 查询集合
     *
     * @param sql
     * @param rowMap 转换一行的 方法
     * @param <T>    每行结果转换后的  类型 实体
     * @return 集合
     */
    public static <T> List<T> executeQuery(String sql, RowMap<T> rowMap, Object... param) {
        List list = new ArrayList();

        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            conn = getConnection();
            stmt = conn.prepareStatement(sql);
            if (param != null) {
                for (int i = 0; i < param.length; i++) {
                    stmt.setObject((i + 1), param[i]);
                }
            }
            rs = stmt.executeQuery();
            while (rs.next()) {
                //解析每一行
                Object obj = rowMap.rowmap(rs);
                list.add(obj);
            }

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

            close(rs, stmt, conn);
        }
        return list;
    }


    //查询一条
    public static <T> T getOne(String sql, RowMap<T> rowMap, Object... param) {

        List<T> list  = executeQuery(sql,rowMap,param);
        if(list !=null && list.size()>0){
            return list.get(0);
        }
        return null;
    }

    //执行更新语句
    public static boolean executeUpdate(String sql, Object... param) {

        Connection conn = null;
        PreparedStatement stmt = null;
        int count = 0;
        try {
            conn = getConnection();
            stmt = conn.prepareStatement(sql.toString());

            if (param != null) {
                for (int i = 0; i < param.length; i++) {
                    stmt.setObject((i + 1), param[i]);
                }
            }
            count = stmt.executeUpdate();

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

           close(null,stmt,conn);
        }
        return count>0;
    }




    public static <T> List<T> executeQuery(String sql, Class clazz, Object... param) {
        List list = new ArrayList();

        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            conn = getConnection();
            stmt = conn.prepareStatement(sql);
            if (param != null) {
                for (int i = 0; i < param.length; i++) {
                    stmt.setObject((i + 1), param[i]);
                }
            }
            rs = stmt.executeQuery();
            ResultSetMetaData meta = rs.getMetaData();
            int count = meta.getColumnCount();
            while (rs.next()) {
                //解析每一行

                Object obj = clazz.newInstance();


                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {

                    field.setAccessible(true);
                    field.set(obj,rs.getObject(field.getName()));

                }
                list.add(obj);
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } finally {

            close(rs, stmt, conn);
        }
        return list;
    }

}

8.2.3 测试类

java
package com.neuedu.util;

import com.neuedu.entity.Account;
import com.neuedu.entity.User;

import java.util.Date;
import java.util.List;

/**
 * 项目:      jdbc
 * 类名:       UtilTest
 * 创建时间:  2020/11/26  14:01
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class UtilTest {


    public static void main(String[] args) {


        int id = 3;
        String sql = "SELECT   id, username,  displayname,   password,  birthday, gender,  telephone, email, last_logintime,  create_time,  valid  FROM user " +
                " where  id > ? and telephone = ?";
        List<User> list = JDBCUtil.executeQuery(sql, (rs) -> {
            User user = new User(
                    rs.getInt("id"),
                    rs.getString("username"),
                    rs.getString("displayname"),
                    rs.getString("password"),
                    rs.getDate("birthday"),
                    rs.getString("gender"),
                    rs.getString("telephone"),
                    rs.getString("email"),
                    rs.getTimestamp("last_logintime"),
                    rs.getTimestamp("create_time"),
                    rs.getString("valid")
            );
            return user;
        }, id, "abc2");


        for (User user : list) {
            System.out.println(user);
        }

        int accountId = 4;
        Account acount = JDBCUtil.getOne("select * from account where id = ?", (rs) -> {
            Account account = new Account(
                    rs.getInt("id"),
                    rs.getString("account_name"),
                    rs.getBigDecimal("amout")
            );
            return account;
        }, accountId);


        System.out.println(acount);


        System.out.println("========================================================================");


        StringBuffer userInsertSql = new StringBuffer();
        userInsertSql.append(" INSERT INTO USER (  username,  displayname,  password,  birthday, gender,  telephone, email     )                            ");
        userInsertSql.append(" VALUES    (  ?,?,?,?,?,? ,? )     ");
        boolean insertSuccess = JDBCUtil.executeUpdate(userInsertSql.toString(),
                "qwer",
                "displayname",
                "password",
                new Date(),
                "1",
                "13888888888",
                "displayname@email.com"
        );


        System.out.println("insertSuccess\t" + insertSuccess);


        accountId = 2;
        List listAccount = JDBCUtil.executeQuery("select * from account where id = ?", Account.class, accountId);
        System.out.println(listAccount.get(0));


    }
}

8.3 反射

8.3.1 定义

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

8.3.2 用途

在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后在最终返回结果的地方对应用的权限进行了校验,对于没有权限的应用返回值是没有意义的缺省值,否则返回实际值起到保护用户的隐私目的。

8.3.3 反射机制的相关类

与Java反射相关的类如下:

类名用途
Class类代表类的实体,在运行的Java应用程序中表示类和接口
Field类代表类的成员变量(成员变量也称为类的属性)
Method类代表类的方法
Constructor类代表类的构造方法

8.3.4 Class类

Class代表类的实体,在运行的Java应用程序中表示类和接口。在这个类中提供了很多有用的方法,这里对他们简单的分类介绍。

  • 获得类相关的方法
方法用途
asSubclass(Class<U> clazz)把传递的类的对象转换成代表其子类的对象
Cast把对象转换成代表类或是接口的对象
getClassLoader()获得类的加载器
getClasses()返回一个数组,数组中包含该类中所有公共类和接口类的对象
getDeclaredClasses()返回一个数组,数组中包含该类中所有类和接口类的对象
forName(String className)根据类名返回类的对象
getName()获得类的完整路径名字
newInstance()创建类的实例
getPackage()获得类的包
getSimpleName()获得类的名字
getSuperclass()获得当前类继承的父类的名字
getInterfaces()获得当前类实现的类或是接口
  • 获得类中属性相关的方法
方法用途
getField(String name)获得某个公有的属性对象
getFields()获得所有公有的属性对象
getDeclaredField(String name)获得某个属性对象
getDeclaredFields()获得所有属性对象
  • 获得类中注解相关的方法
方法用途
getAnnotation(Class<A> annotationClass)返回该类中与参数类型匹配的公有注解对象
getAnnotations()返回该类所有的公有注解对象
getDeclaredAnnotation(Class<A> annotationClass)返回该类中与参数类型匹配的所有注解对象
getDeclaredAnnotations()返回该类所有的注解对象
  • 获得类中构造器相关的方法
方法用途
getConstructor(Class...<?> parameterTypes)获得该类中与参数类型匹配的公有构造方法
getConstructors()获得该类的所有公有构造方法
getDeclaredConstructor(Class...<?> parameterTypes)获得该类中与参数类型匹配的构造方法
getDeclaredConstructors()获得该类所有构造方法
  • 获得类中方法相关的方法
方法用途
getMethod(String name, Class...<?> parameterTypes)获得该类某个公有的方法
getMethods()获得该类所有公有的方法
getDeclaredMethod(String name, Class...<?> parameterTypes)获得该类某个方法
getDeclaredMethods()获得该类所有方法
  • 类中其他重要的方法
方法用途
isAnnotation()如果是注解类型则返回true
isAnnotationPresent(Class<? extends Annotation> annotationClass)如果是指定类型注解类型则返回true
isAnonymousClass()如果是匿名类则返回true
isArray()如果是一个数组类则返回true
isEnum()如果是枚举类则返回true
isInstance(Object obj)如果obj是该类的实例则返回true
isInterface()如果是接口类则返回true
isLocalClass()如果是局部类则返回true
isMemberClass()如果是内部类则返回true

8.3.5 Field类

Field代表类的成员变量(成员变量也称为类的属性)。

方法用途
equals(Object obj)属性与obj相等则返回true
get(Object obj)获得obj中对应的属性值
set(Object obj, Object value)设置obj中对应属性值

8.3.6 Method类

Method代表类的方法。

方法用途
invoke(Object obj, Object... args)传递object对象及参数调用该对象对应的方法

8.3.7 Constructor类

Constructor代表类的构造方法。

方法用途
newInstance(Object... initargs)根据传递的参数创建类的对象

8.3.8 实例

java
package com.neuedu.entity;

import java.util.Date;

/**
 * 项目:      jdbc
 * 类名:       User
 * 创建时间:  2020/11/25  14:40
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io 实体类
 */
public class User {
    private Integer id;
    private String username;
    private String displayname;
    private String password;
    private Date birthday;
    private String gender;
    private String telephone;
    private String email;
    private Date last_logintime;
    private Date create_time;
    private String valid;

    public User() {
    }

    public User(Integer id, String username, String displayname, String password, Date birthday, String gender, String telephone, String email, Date last_logintime, Date create_time, String valid) {
        this.id = id;
        this.username = username;
        this.displayname = displayname;
        this.password = password;
        this.birthday = birthday;
        this.gender = gender;
        this.telephone = telephone;
        this.email = email;
        this.last_logintime = last_logintime;
        this.create_time = create_time;
        this.valid = valid;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getDisplayname() {
        return displayname;
    }

    public void setDisplayname(String displayname) {
        this.displayname = displayname;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Date getLast_logintime() {
        return last_logintime;
    }

    public void setLast_logintime(Date last_logintime) {
        this.last_logintime = last_logintime;
    }

    public Date getCreate_time() {
        return create_time;
    }

    public void setCreate_time(Date create_time) {
        this.create_time = create_time;
    }

    public String getValid() {
        return valid;
    }

    public void setValid(String valid) {
        this.valid = valid;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", displayname='" + displayname + '\'' +
                ", password='" + password + '\'' +
                ", birthday=" + birthday +
                ", gender='" + gender + '\'' +
                ", telephone='" + telephone + '\'' +
                ", email='" + email + '\'' +
                ", last_logintime=" + last_logintime +
                ", create_time=" + create_time +
                ", valid='" + valid + '\'' +
                '}';
    }
}
java
package com.neuedu.reflect;

import com.neuedu.entity.User;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * 项目:      jdbc
 * 类名:       reflect
 * 创建时间:  2020/11/26  16:00
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class MyFeflect {


    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //1 访问class
        //1.1 类名.class
        //1.2 Class.forName
        //1.3 obj.getClass()
        Class<User> clazz = User.class;
        Class clazz2  = Class.forName("com.neuedu.entity.User");
        Class class3 = new User().getClass();


        //2 实例化对象
        User user1 = clazz.newInstance();
        System.out.println(user1);

        //3 访问属性
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //获取访问修饰符
            String modifiers = Modifier.toString(field.getModifiers());
            //获取属性名字
            String fieldName = field.getName();
            System.out.println(modifiers+"\t" +fieldName);
        }


        String property = "username";
        Field filed = clazz.getDeclaredField(property);
        //获取属性,get、设值属性set
        filed.setAccessible(true);
        filed.set(user1,"admin");

        System.out.println(user1);



        //4 获取方法
        String label = "Id";

        //所有声明的方法
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
//            System.out.println("method.getName()\t"+method.getName());
        }
        Method setIdMethod = clazz.getMethod("set"+label,Integer.class);
        System.out.println(setIdMethod.getName());


        //5 执行对象的方法setId、setUserName
//        user1.setId(100);
        setIdMethod.invoke(user1,10);

        System.out.println(user1);

    }
}

8.4 注解编程

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。

Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。 当然它也支持自定义 Java 标注。

网上很多关于 Java Annotation 的文章,看得人眼花缭乱。Java Annotation 本来很简单的,结果说的人没说清楚;弄的看的人更加迷糊。

我按照自己的思路,对 Annotation 进行了整理。理解 Annotation 的关键,是理解 Annotation 的语法和用法,对这些内容,我都进行了详细说明;理解 Annotation 的语法和用法之后,再看 Annotation 的框架图,可能有更深刻体会。废话就说这么多,下面开始对 Annotation 进行说明。若您发现文章中存在错误或不足的地方,希望您能指出!

8.4.1 内置的注解

Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。

作用在代码的注解是

  • @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
  • @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
  • @SuppressWarnings - 指示编译器去忽略注解中声明的警告。

作用在其他注解的注解(或者说 元注解)是:

  • @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
  • @Documented - 标记这些注解是否包含在用户文档中。
  • @Target - 标记这个注解应该是哪种 Java 成员。
  • @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)

从 Java 7 开始,额外添加了 3 个注解:

  • @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
  • @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
  • @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。

8.4.2 Annotation 架构

img

从中,我们可以看出:

(01) 1 个 Annotation 和 1 个 RetentionPolicy 关联。

可以理解为:每1个Annotation对象,都会有唯一的RetentionPolicy属性。

(02) 1 个 Annotation 和 1~n 个 ElementType 关联。

可以理解为:对于每 1 个 Annotation 对象,可以有若干个 ElementType 属性。

(03) Annotation 有许多实现类,包括:Deprecated, Documented, Inherited, Override 等等。

Annotation 的每一个实现类,都 "和 1 个 RetentionPolicy 关联" 并且 " 和 1~n 个 ElementType 关联"。

下面,我先介绍框架图的左半边(如下图),即 Annotation, RetentionPolicy, ElementType;然后在就 Annotation 的实现类进行举例说明。

img


8.4.3 Annotation 组成部分

java Annotation 的组成中,有 3 个非常重要的主干类。它们分别是:

Annotation.java

java
package java.lang.annotation;
 public interface Annotation {
 
   boolean equals(Object obj);
 
   int hashCode();
 
   String toString();
 
   Class<? extends> Annotation> annotationType();
 }

ElementType.java

java
 package  java.lang.annotation;

  public   enum  ElementType {
   TYPE,        /* 类、接口(包括注释类型)或枚举声明  */

   FIELD,        /* 字段声明(包括枚举常量)  */

   METHOD,       /* 方法声明  */

   PARAMETER,      /* 参数声明  */

   CONSTRUCTOR,     /* 构造方法声明  */

   LOCAL_VARIABLE,   /* 局部变量声明  */

   ANNOTATION_TYPE,   /* 注释类型声明  */

    PACKAGE        /* 包声明  */
 }

RetentionPolicy.java

java
package java.lang.annotation;
public enum RetentionPolicy {
    SOURCE,            /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了  */

    CLASS,             /* 编译器将Annotation存储于类对应的.class文件中。默认行为  */

    RUNTIME            /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */
}

说明:

(01) Annotation 就是个接口。

"每 1 个 Annotation" 都与 "1 个 RetentionPolicy" 关联,并且与 "1~n 个 ElementType" 关联。可以通俗的理解为:每 1 个 Annotation 对象,都会有唯一的 RetentionPolicy 属性;至于 ElementType 属性,则有 1~n 个。

(02) ElementType 是 Enum 枚举类型,它用来指定 Annotation 的类型。

"每 1 个 Annotation" 都与 "1~n 个 ElementType" 关联。当 Annotation 与某个 ElementType 关联时,就意味着:Annotation有了某种用途。例如,若一个 Annotation 对象是 METHOD 类型,则该 Annotation 只能用来修饰方法。

(03) RetentionPolicy 是 Enum 枚举类型,它用来指定 Annotation 的策略。通俗点说,就是不同 RetentionPolicy 类型的 Annotation 的作用域不同。

"每 1 个 Annotation" 都与 "1 个 RetentionPolicy" 关联。

  • a) 若 Annotation 的类型为 SOURCE,则意味着:Annotation 仅存在于编译器处理期间,编译器处理完之后,该 Annotation 就没用了。 例如," @Override" 标志就是一个 Annotation。当它修饰一个方法的时候,就意味着该方法覆盖父类的方法;并且在编译期间会进行语法检查!编译器处理完后,"@Override" 就没有任何作用了。
  • b) 若 Annotation 的类型为 CLASS,则意味着:编译器将 Annotation 存储于类对应的 .class 文件中,它是 Annotation 的默认行为。
  • c) 若 Annotation 的类型为 RUNTIME,则意味着:编译器将 Annotation 存储于 class 文件中,并且可由JVM读入。

这时,只需要记住"每 1 个 Annotation" 都与 "1 个 RetentionPolicy" 关联,并且与 "1~n 个 ElementType" 关联。学完后面的内容之后,再回头看这些内容,会更容易理解。


8.4.4 java 自带的 Annotation

理解了上面的 3 个类的作用之后,我们接下来可以讲解 Annotation 实现类的语法定义了。

1)Annotation 通用定义

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 {
}

说明:

上面的作用是定义一个 Annotation,它的名字是 MyAnnotation1。定义了 MyAnnotation1 之后,我们可以在代码中通过 "@MyAnnotation1" 来使用它。 其它的,@Documented, @Target, @Retention, @interface 都是来修饰 MyAnnotation1 的。下面分别说说它们的含义:

(01) @interface

使用 @interface 定义注解时,意味着它实现了 java.lang.annotation.Annotation 接口,即该注解就是一个Annotation。

定义 Annotation 时,@interface 是必须的。

注意:它和我们通常的 implemented 实现接口的方法不同。Annotation 接口的实现细节都由编译器完成。通过 @interface 定义注解后,该注解不能继承其他的注解或接口。

(02) @Documented

类和方法的 Annotation 在缺省情况下是不出现在 javadoc 中的。如果使用 @Documented 修饰该 Annotation,则表示它可以出现在 javadoc 中。

定义 Annotation 时,@Documented 可有可无;若没有定义,则 Annotation 不会出现在 javadoc 中。

(03) @Target(ElementType.TYPE)

前面我们说过,ElementType 是 Annotation 的类型属性。而 @Target 的作用,就是来指定 Annotation 的类型属性。

@Target(ElementType.TYPE) 的意思就是指定该 Annotation 的类型是 ElementType.TYPE。这就意味着,MyAnnotation1 是来修饰"类、接口(包括注释类型)或枚举声明"的注解。

定义 Annotation 时,@Target 可有可无。若有 @Target,则该 Annotation 只能用于它所指定的地方;若没有 @Target,则该 Annotation 可以用于任何地方。

(04) @Retention(RetentionPolicy.RUNTIME)

前面我们说过,RetentionPolicy 是 Annotation 的策略属性,而 @Retention 的作用,就是指定 Annotation 的策略属性。

@Retention(RetentionPolicy.RUNTIME) 的意思就是指定该 Annotation 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将该 Annotation 信息保留在 .class 文件中,并且能被虚拟机读取。

定义 Annotation 时,@Retention 可有可无。若没有 @Retention,则默认是 RetentionPolicy.CLASS。

通过上面的示例,我们能理解:@interface 用来声明 Annotation,@Documented 用来表示该 Annotation 是否会出现在 javadoc 中, @Target 用来指定 Annotation 的类型,@Retention 用来指定 Annotation 的策略。

理解这一点之后,我们就很容易理解 java 中自带的 Annotation 的实现类,即 Annotation 架构图的右半边。如下图:

img

java 常用的 Annotation:

@Deprecated  -- @Deprecated 所标注内容,不再被建议使用。
@Override    -- @Override 只能标注方法,表示该方法覆盖父类中的方法。
@Documented  -- @Documented 所标注内容,可以出现在javadoc中。
@Inherited   -- @Inherited只能被用来标注“Annotation类型”,它所标注的Annotation具有继承性。
@Retention   -- @Retention只能被用来标注“Annotation类型”,而且它被用来指定Annotation的RetentionPolicy属性。
@Target      -- @Target只能被用来标注“Annotation类型”,而且它被用来指定Annotation的ElementType属性。
@SuppressWarnings -- @SuppressWarnings 所标注内容产生的警告,编译器会对这些警告保持静默。

由于 "@Deprecated 和 @Override" 类似,"@Documented, @Inherited, @Retention, @Target" 类似;下面,我们只对 @Deprecated, @Inherited, @SuppressWarnings 这 3 个 Annotation 进行说明。

2.1) @Deprecated

@Deprecated 的定义如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Deprecated {
}

说明:

  • (01) @interface -- 它的用来修饰 Deprecated,意味着 Deprecated 实现了 java.lang.annotation.Annotation 接口;即 Deprecated 就是一个注解。 (02) @Documented -- 它的作用是说明该注解能出现在 javadoc 中。
  • (03) @Retention(RetentionPolicy.RUNTIME) -- 它的作用是指定 Deprecated 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将Deprecated 的信息保留在 .class 文件中,并且能被虚拟机读取。
  • (04) @Deprecated 所标注内容,不再被建议使用。

例如,若某个方法被 @Deprecated 标注,则该方法不再被建议使用。如果有开发人员试图使用或重写被 @Deprecated 标示的方法,编译器会给相应的提示信息。示例如下:

DeprecatedTest.java

java
import java.util.Date;
import java.util.Calendar;

public class DeprecatedTest {

    // Date是日期/时间类。java已经不建议使用该类了
    private static void testDate() {
        Date date = new Date(113, 8, 25);
        System.out.println(date.getYear());
    }
    // Calendar是日期/时间类。java建议使用Calendar取代Date表示"日期/时间"
    private static void testCalendar() {
        Calendar cal = Calendar.getInstance();
        System.out.println(cal.get(Calendar.YEAR));
    }
   
    public static void main(String[] args) {
        testDate();
        testCalendar();
    }
}

说明:

上面是 IDEA 中的截图,比较类中 "testDate() 和 testCalendar()" 。

testDate() 调用了 Date 的相关方法,而 java 已经建议不再使用 Date 操作日期/时间。因此,在调用 Date的API 时,会产生警告信息,途中的 warnings。

testCalendar() 调用了 Calendar 的 API 来操作日期/时间,java 建议用 Calendar 取代 Date。因此,操作 Calendar 不会产生 warning。

2.2) @Inherited

@Inherited 的定义如下:

java
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

说明:

  • (01) @interface -- 它的用来修饰 Inherited,意味着 Inherited 实现了 java.lang.annotation.Annotation 接口;即 Inherited 就是一个注解。
  • (02) @Documented -- 它的作用是说明该注解能出现在 javadoc 中。
  • (03) @Retention(RetentionPolicy.RUNTIME) -- 它的作用是指定 Inherited 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将 Inherited 的信息保留在 .class 文件中,并且能被虚拟机读取。
  • (04) @Target(ElementType.ANNOTATION_TYPE) -- 它的作用是指定 Inherited 的类型是 ANNOTATION_TYPE。这就意味着,@Inherited 只能被用来标注 "Annotation 类型"。
  • (05) @Inherited 的含义是,它所标注的Annotation将具有继承性。

2.3) @SuppressWarnings

@SuppressWarnings 的定义如下:

java
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}

说明:

(01) @interface -- 它的用来修饰 SuppressWarnings,意味着 SuppressWarnings 实现了 java.lang.annotation.Annotation 接口;即 SuppressWarnings 就是一个注解。

(02) @Retention(RetentionPolicy.SOURCE) -- 它的作用是指定 SuppressWarnings 的策略是 RetentionPolicy.SOURCE。这就意味着,SuppressWarnings 信息仅存在于编译器处理期间,编译器处理完之后 SuppressWarnings 就没有作用了。

(03) @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) -- 它的作用是指定 SuppressWarnings 的类型同时包括TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE。

  • TYPE 意味着,它能标注"类、接口(包括注释类型)或枚举声明"。
  • FIELD 意味着,它能标注"字段声明"。
  • METHOD 意味着,它能标注"方法"。
  • PARAMETER 意味着,它能标注"参数"。
  • CONSTRUCTOR 意味着,它能标注"构造方法"。
  • LOCAL_VARIABLE 意味着,它能标注"局部变量"。

(04) String[] value(); 意味着,SuppressWarnings 能指定参数

(05) SuppressWarnings 的作用是,让编译器对"它所标注的内容"的某些警告保持静默。例如,"@SuppressWarnings(value={"deprecation", "unchecked"})" 表示对"它所标注的内容"中的 "SuppressWarnings 不再建议使用警告"和"未检查的转换时的警告"保持沉默。

8.4.5 Annotation 的作用

Annotation 是一个辅助类,它在 Junit、Struts、Spring 等工具框架中被广泛使用。

我们在编程中经常会使用到的 Annotation 作用有:

  • 1)编译检查

Annotation 具有"让编译器进行编译检查的作用"。

例如,@SuppressWarnings, @Deprecated 和 @Override 都具有编译检查作用。

(01) 关于 @SuppressWarnings 和 @Deprecated,已经在"第3部分"中详细介绍过了。这里就不再举例说明了。

(02) 若某个方法被 @Override 的标注,则意味着该方法会覆盖父类中的同名方法。如果有方法被 @Override 标示,但父类中却没有"被 @Override 标注"的同名方法,则编译器会报错。

    1. 在反射中使用 Annotation

在反射的 Class, Method, Field 等函数中,有许多于 Annotation 相关的接口。

这也意味着,我们可以在反射中解析并使用 Annotation。

    1. 根据 Annotation 生成帮助文档

通过给 Annotation 注解加上 @Documented 标签,能使该 Annotation 标签出现在 javadoc 中。

    1. 能够帮忙查看查看代码

通过 @Override, @Deprecated 等,我们能很方便的了解程序的大致结构。

另外,我们也可以通过自定义 Annotation 来实现一些功能。

8.5 利用注解、反射重新封装jdbc工具类

利用注解解决字段名和属性名不一致的情况,利用反射封装单行结果映射的过程。

8.5.1 定义注解

java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 项目:      jdbc
 * 类名:       Column
 * 创建时间:  2020/11/27  9:04
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */


//能够出现的位置 可以在属性上声明
@Target(ElementType.FIELD)

//存活的声明周期,运行期间有效
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {

    String value();
}

8.5.2 工具类

java
package com.neuedu.util;

import com.neuedu.entity.User;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 项目:      jdbc
 * 类名:       JDBCUtil
 * 创建时间:  2020/11/26  13:55
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class JDBCUtil {


    public static final String driver = "com.mysql.jdbc.Driver";
    //连接的数据 mysql的默认端口 3306  Oracle 1521
    public static final String url = "jdbc:mysql://127.0.0.1:3306/jdbc_his?characterEncoding=utf8&useUnicode=true&useSSL=false";
    //连接数据库的用户名、密码
    public static final String username = "root";
    public static final String password = "root";


    static {
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    /**
     * 加载数据库连接
     *
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    private static Connection getConnection() throws ClassNotFoundException, SQLException {

        Connection conn = DriverManager.getConnection(url, username, password);
        return conn;
    }


    private static void close(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    private static void close(PreparedStatement stmt) {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    private static void close(ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    private static void close(ResultSet rs, PreparedStatement stmt, Connection conn) {
        close(rs);
        close(stmt);
        close(conn);
    }

    /**
     * 查询集合
     *
     * @param sql
     * @param rowMap 转换一行的 方法
     * @param <T>    每行结果转换后的  类型 实体
     * @return 集合
     */
    public static <T> List<T> executeQuery(String sql, RowMap<T> rowMap, Object... param) {
        List list = new ArrayList();

        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            conn = getConnection();
            stmt = conn.prepareStatement(sql);
            if (param != null) {
                for (int i = 0; i < param.length; i++) {
                    stmt.setObject((i + 1), param[i]);
                }
            }
            rs = stmt.executeQuery();
            while (rs.next()) {
                //解析每一行
                Object obj = rowMap.rowmap(rs);
                list.add(obj);
            }

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

            close(rs, stmt, conn);
        }
        return list;
    }


    //查询一条
    public static <T> T getOne(String sql, RowMap<T> rowMap, Object... param) {

        List<T> list  = executeQuery(sql,rowMap,param);
        if(list !=null && list.size()>0){
            return list.get(0);
        }
        return null;
    }

    //执行更新语句
    public static boolean executeUpdate(String sql, Object... param) {

        Connection conn = null;
        PreparedStatement stmt = null;
        int count = 0;
        try {
            conn = getConnection();
            stmt = conn.prepareStatement(sql.toString());

            if (param != null) {
                for (int i = 0; i < param.length; i++) {
                    stmt.setObject((i + 1), param[i]);
                }
            }
            count = stmt.executeUpdate();

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

           close(null,stmt,conn);
        }
        return count>0;
    }




    public static <T> List<T> executeQuery(String sql, Class clazz, Object... param) {
        List list = new ArrayList();

        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            conn = getConnection();
            stmt = conn.prepareStatement(sql);
            if (param != null) {
                for (int i = 0; i < param.length; i++) {
                    stmt.setObject((i + 1), param[i]);
                }
            }
            rs = stmt.executeQuery();
            ResultSetMetaData meta = rs.getMetaData();
            int count = meta.getColumnCount();
            while (rs.next()) {
                //解析每一行

                Object obj = clazz.newInstance();
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {

                    field.setAccessible(true);
                    try {

                        //@Column  account_name
                        String name = field.getName();
                        if(field.isAnnotationPresent(Column.class)){//如果属性上有有Column注解,则使用Column的属性作为字段名
                            Column column = field.getAnnotation(Column.class);
                            name = column.value();
                        }

                        field.set(obj, rs.getObject(name));
                    }catch (Exception e){
                        System.out.println("没有字段"+field.getName());
                    }

                }
                list.add(obj);
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } finally {

            close(rs, stmt, conn);
        }
        return list;
    }

}

Released under the MIT License.