JDBC笔记(MySQL)

JDBC学习

JDBC结构图

1.JDBC简介

Java数据库连接,(Java Database Connectivity,简称JDBC),是Java语言用来规范客户端程序访问并操作数据库的接口,
JDBC接口是一套class文件,由SUM公司负责制定JDBC的规范。

JDBC作为规范与各大数据库连接

1.1 学习JDBC数据库

-- 里面有外键,但我不会使用到
SET FOREIGN_KEY_CHECKS=0;
​
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` int(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `studentName` varchar(20) NOT NULL COMMENT '姓名',
  `password` varchar(50) NOT NULL COMMENT '密码',
  `birthday` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '生日',
  `classID` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `class_id` (`classID`),
  CONSTRAINT `class_id` FOREIGN KEY (`classID`) REFERENCES `class` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
​
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', '张三', 'e10adc3949ba59abbe56e057f20f883e', '2021-02-01 00:00:00', '1');
INSERT INTO `student` VALUES ('2', '张于', 'ffe7a019bc8c991d28b894b9aaac2ff7', '2022-03-08 09:29:15', '3');
INSERT INTO `student` VALUES ('3', '吉吉', '5bd2026f128662763c532f2f4b6f2476', '2022-03-08 10:07:46', '2');
INSERT INTO `student` VALUES ('4', '王五', '678987', '2022-09-16 23:50:53', '1');
INSERT INTO `student` VALUES ('5', '李四', '123456', '2022-09-17 00:00:00', '2');
INSERT INTO `student` VALUES ('6', '李四', '123456', '2022-09-17 00:00:00', '2');

2.JDBC使用步骤

1.注册驱动
2.加载数据库驱动,使用 DriverManager 获取连接对象
3.使用 Connection 创建 PreparedStatement 语句对象
4.设置 SQL 语句中的参数值,执行 SQL 语句
5.操作结果集
6.回收数据库资源,包括关闭 ResultSet、Statement 和 Connection 等资源

JDBC简单实例

public class JDBCSelectTest {
    //      主启动类
    public static void main(String[] args) throws Exception {
        jdbcStep();
    }
    /**
     *      JDBC简单实现步骤
     * @throws Exception    异常处理
     */
    public static void jdbcStep() throws Exception {
        //  1.注册驱动,注意mysql5驱动不一样,是com.mysql.jdbc.Driver
        Class.forName("com.mysql.cj.jdbc.Driver");
        //  2.创建连接对象
        Connection connection= DriverManager
                .getConnection("jdbc:mysql://localhost:3306/sql_study?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8"
                ,"root","123456");
        //  3.创建预编译器PreparedStatement,(Statement存储简单SQL注入,没有PreparedStatement安全)
        String sql="select * from student where id=?";
        PreparedStatement ps=connection.prepareStatement(sql);
       
        ps.setObject(1,1);
        //  4.执行SQL,获取结果集
        ResultSet rs = ps.executeQuery();
        //  5.处理结果集
        System.out.println(rs.next()?"有结果值":"没有结果值!");
        //  6.释放资源
        connection.close();
    }
}

3.数据库的增删查改

增删查改

    /**
     * 创建一个Connection
     * @return  connection
     */
public static Connection getConnection() {
    Connection connection=null;
    try{
        //  1.注册驱动,注意mysql5驱动不一样,是com.mysql.jdbc.Driver
        Class.forName("com.mysql.cj.jdbc.Driver");
        //  2.创建连接对象
        connection= DriverManager
            .getConnection("jdbc:mysql://localhost:3306/sql_study?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8"
                           ,"root","123456");
    } catch (Exception e) {
        e.printStackTrace();
    }
    return connection;
}
​
​
    /**
     *      添加学生
     * @param student   学生对象
     */
public static void addStudent(Student student){
    String sql="insert into student value(default,?,?,?,?)";
    try{
        PreparedStatement ps=getConnection().prepareStatement(sql);
        ps.setObject(1,student.getStudentName());
        ps.setObject(2,student.getPassword());
        ps.setObject(3,student.getBirthday());
        ps.setObject(4,student.getClassID());
        System.out.println(ps.executeUpdate()>0?"添加成功":"添加失败");
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }
}
​
    /**
     *      更新学生
     */
public static void updateStudent(){
    String sql="update student set studentName=? where id=?";
    try{
        PreparedStatement ps=getConnection().prepareStatement(sql);
        ps.setObject(1,"空空");
        ps.setObject(2,5);
        System.out.println(ps.executeUpdate()>0?"更新成功":"更新失败");
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }
}
​
    /**
     *      删除学生
     * @param id    学生id
     */
public static void deleteStudent(int id){
    String sql="delete from student where id=?";
    try{
        PreparedStatement ps=getConnection().prepareStatement(sql);
        ps.setObject(1,id);
        System.out.println(ps.executeUpdate()>0?"删除成功":"删除失败");
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }
}
​
​
    /**
     *      查询学生
     * @param name  学生名字
     * @param password  学生密码
     */
public static void selectStudent(String name,String password){
    String sql="select * from student where studentName=? and password=?";
    try{
        PreparedStatement ps=getConnection().prepareStatement(sql);
        ps.setObject(1,name);
        ps.setObject(2,password);
        ResultSet rs = ps.executeQuery();
        while (rs.next()){
            int id = rs.getInt("id");
            String studentName = rs.getString("studentName");
            String password1 = rs.getString("password");
            LocalDate localDate = rs.getDate("birthday").toLocalDate();
            LocalDateTime birthday = localDate.atStartOfDay();
            int classID = rs.getInt("classID");
            Student student=new Student(id,studentName,password1,birthday,classID);
            System.out.println(student.toString());
        }
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }
}

4.JDBC中的对象

4.1 Connection

Connection 接口:代表数据库连接对象
​
创建语句对象Statement createStatement():创建一个 Statement 对象PreparedStatement prepareStatement(String sql):创建一个 PreparedStatement 对象PreparedStatement prepareStatement(String sql, int autoGeneratedKeys):创建一个 PreparedStatement 对象,并设置该对象是否能获取自动生成的主键
​
控制事务void setAutoCommit(boolean autoCommit):false 为关闭自动提交,开启事务(MySQL 默认打开自动提交)
void commit():提交事务,并释放所持有的数据库锁
void rollback():回滚事务,并释放所持有的数据库锁

事务提交和回滚

CREATE TABLE account(
   id INT PRIMARY KEY AUTO_INCREMENT,
   `name` VARCHAR(40),
   money FLOAT
);
​
INSERT INTO account(`name`,money) VALUES('A',1000);
INSERT INTO account(`name`,money) VALUES('B',1000);
INSERT INTO account(`name`,money) VALUES('C',1000);
   @Test
    public void test() {
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/student_study?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";
​
        Connection connection = null;
​
        //1.加载驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.连接数据库,代表数据库
             connection = DriverManager.getConnection(url, username, password);
​
            //3.通知数据库开启事务,false 开启
            connection.setAutoCommit(false);
​
            String sql = "update account set money = money-100 where name = 'A'";
            connection.prepareStatement(sql).executeUpdate();
​
            //制造错误
            //int i = 1/0;
​
            String sql2 = "update account set money = money+100 where name = 'B'";
            connection.prepareStatement(sql2).executeUpdate();
​
            connection.commit();//以上两条SQL都执行成功了,就提交事务!
            System.out.println("success");
        } catch (Exception e) {
            try {
                //如果出现异常,就通知数据库回滚事务
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

4.2 Statement

Statement 接口:用于执行静态 SQL 语句(将 SQL 语句发送到数据库)
​
执行语句int executeUpdate(String sql):执行DML语句时返回受影响的行数;
int executeUpdate(String sql, int autoGeneratedKeys):执行给定的 DML 语句,并设置此 Statement 生成的自动生成键是否能用于获取
ResultSet executeQuery(String sql):执行DQL语句,并返回査询结果对应的 ResultSet 对象
​
批量更新void addBatch(String sql):将给定的SQL命令添加到此 Statement 对象的当前命令列表中
int[] executeBatch():执行一批命令void clearBatch():清空此 Statement 对象的当前 SQL 命令列表
​
获取自动生成主键ResultSet getGeneratedKeys():获取由于执行此 Statement 对象而创建的所有自动生成的主键

4.3 PreparedStatement

PreparedStatement 接口,Statement 的子接口,用于执行带占位符(?)参数的 SQL 语句
​
给参数设值即添加到批处理setXxx(int parameterIndex, Xxx value):根据索引(从 1 开始)
​
执行语句int executeUpdate():执行 DML 语句或 DDL 语句(无须接收 SQL 字符串)ResultSet executeQuery():执行 DQL 语句,不需接受sql参数。preparedStatement可以阻止简单sql注入

4.4 ResultSet

boolean next():将光标从当前行移动到下一行(光标的初始位置是第一行之前)Xxx getXxx(int columnIndex):获取当前行中的指定列索引(从 1 开始)的数据Xxx getXxx(String columnName):获取当前行中的指定列名的数据

5.properties文件

在实际开发中,我们一般情况下,会把配置相关的信息,放在 xx.properties 中保存。也方便修改

  • properties文件应放在resources包下。可以了解classpath

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/sql_study?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
user=root
password=123456
public class PropertiesJdbcTest {
    public static void readLoading() throws IOException {
        //  读取放在resources包下的properties文件
        InputStream resourceAsStream = PropertiesJdbcTest.class.getClassLoader().getResourceAsStream("db.properties");
        //  Properties实例     
        Properties properties=new Properties();
        //  加载properties文件
        properties.load(resourceAsStream);
        String driver=properties.getProperty("driver");
        System.out.println(driver);
    }
​
    public static void main(String[] args) throws IOException {
        readLoading();
    }
}

6.JDCUtils工具类

<!-- Mysql数据库依赖 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.29</version>
</dependency>

JDBC工具类

/**
 * @Author Mga
 * @Date 2022/9/16 9:59
 * @注释 JDBC数据库工具类
 * 其中有两个方法需要注意querySql()、query
 * 使用要求数据库字段要和pojo字段名一致,不然反射来实例对象有误
 */
​
public class JDBCUtils {
​
    //  创建数据库连接对象
    private Connection connection = null;
​
    /**
     * 利用构造方法给Connection赋值
     */
    public JDBCUtils() {
        try {
            //  加载数据库驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //  数据库连接常量
            String url = "jdbc:mysql://localhost:3306/sql_study?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8";
            String username = "root";
            String password = "123456";
            connection = DriverManager.getConnection(url, username, password);
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
    }
​
​
    /**
     * SQL查询
     *
     * @param sql
     * @param t
     * @param objects
     * @param <T>
     * @return
     */
    public <T> List<T> querySql(String sql, T t, Object... objects) {
        //声明jdbc变量
        List<T> list = new ArrayList<>();
        try {
            //  创建预编译器
            PreparedStatement ps = connection.prepareStatement(sql);
            //给占位符赋值
            if (objects != null) {
                for (int i = 0; i < objects.length; i++) {
                    ps.setObject((i + 1), objects[i]);
                }
            }
            //  执行预编译器
            ResultSet resultSet = ps.executeQuery();
​
            //  这下面就是利用反射来创建一个传来的参数T
            //  获取结果集所有字段的信息
            ResultSetMetaData metaData = resultSet.getMetaData();
            //  获取字段数量
            int columnCount = metaData.getColumnCount();
            //  遍历resultSet
            while (resultSet.next()) {
                //  利用反射创建Class对象
                Class<?> object = t.getClass();
                //  实例化class对象
                try {
                    T o = (T) object.newInstance();
                    for (int count = 1; count <= columnCount; count++) {
                        //  获取单个字段
                        String columnName = metaData.getColumnName(count);
                        //  获取字段对应的setter方法
                        String methodName = "set" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1);
                        //获取字段java类型的完全限定名
                        String columnClassName = metaData.getColumnClassName(count);
                        //  创建方法对象
                        Method method = object.getDeclaredMethod(methodName, Class.forName(columnClassName));
                        //调用setter方法,执行对象属性赋值
                        method.invoke(o, resultSet.getObject(columnName));
                    }
                    list.add(o);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }
​
    /**
     * SQL修改 SQL删除 SQL添加
     *
     * @param sql
     * @param objects
     * @return
     */
    public boolean updateExecute(String sql, Object... objects) {
        boolean flog = false;
        try {
            //  创建controlIndex来控制预编译器赋值
            int controlIndex = 1;
            PreparedStatement ps = connection.prepareStatement(sql);
            //  该字段赋值
            for (Object object : objects) {
                ps.setObject(controlIndex++, object);
            }
            flog = ps.executeUpdate() > 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flog;
    }
​
    /**
     * 查询类
     *
     * @param sql
     * @return
     */
    public ResultSet query(String sql, List<Object> params) {
        try {
            //准备好的报表/SQL
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            if (params != null) {
                int index = 1;
                for (Object param : params) {
                    preparedStatement.setObject(index++, param);
                }
            }
            //执行准备好的报表/SQL
            ResultSet resultSet = preparedStatement.executeQuery();
            return resultSet;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我愿为一粒沙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值