java学习与应用(3.6.2)--JDBC

2020-02-18 13:56:29 浏览数 (1)

说明

越来越晕了,教程和代码示范来自黑马程序员。用了再看吧。

JDBC

JDBC(Java数据库连接的接口)用于统一java代码操作各种数据库。(需要实现类,是数据库厂商提供jar包完成)。 步骤为,导入jar包(可以使用idea的右键添加到库),注册驱动,获取连接对象,定义sql,获取对象,执行语句,处理结果,释放资源。 Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "root"); String sql = "update account set balance = 2000 where id = 1";Statement stmt = conn.createStatement(); int count = stmt.executeUpdate(sql);System.out.println(count);stmt.close();conn.close(); DriverManager :驱动管理对象,Connection :数据库连接对象,Statement :执行sql的对象,ResultSet :结果集对象,Preparedstatement :执行sql的对象 com.mysql.jdbc.Driver类中的静态代码块,执行了注册驱动的操作(使用哪个数据库驱动jar(mysql5以后可以省略,在META-INF.service.java.sql.Driver中自动注册))。 DriverManager对象中静态方法getConnection使用格式如:jdbc:mysql://ip:端口/数据库名。(本地地址3306可以省略ip和端口)。 Connection对象中获取对象方法:createStatement( ),preparedStatement(sql),事务相关:开启: setAutoCommit(boolean autoCommit) ,提交: commit(),回滚: rollback() Statement对象,execute方法(执行任意sql),executeUpdate(执行DML语句(insert,update,delete),DDL语句(create,alter,drop)),返回影响行数(DML有)判断是否成功。executeQuery语句,执行DQL语句(select)。 实例代码:外部的变量,trycatchfinally格式,释放等。 ResultSet结果集对象,作为executeQuery的返回值,封装查询结果,其中的next方法向下移动游标,getXxx获取数据(某一列,Xxx为数据类型,可传入列编号[编号]和列名称)。一般使用while循环判断并执行。 定义抽取JDBC工具类(见代码下),用于简化代码,添加配置文件写入信息,通过静态代码块(只需要读取一次)获取properties配置信息,通过类加载器动态获取绝对路径。

代码语言:javascript复制
  1 package cn.itcast.util;
  2 
  3 import java.io.FileReader;
  4 import java.io.IOException;
  5 import java.net.URL;
  6 import java.sql.*;
  7 import java.util.Properties;
  8 
  9 /**
 10  * JDBC工具类
 11  */
 12 public class JDBCUtils {
 13     private static String url;
 14     private static String user;
 15     private static String password;
 16     private static String driver;
 17     /**
 18      * 文件的读取,只需要读取一次即可拿到这些值。使用静态代码块
 19      */
 20     static{
 21         //读取资源文件,获取值。
 22 
 23         try {
 24             //1. 创建Properties集合类。
 25             Properties pro = new Properties();
 26 
 27             //获取src路径下的文件的方式--->ClassLoader 类加载器
 28             ClassLoader classLoader = JDBCUtils.class.getClassLoader();
 29             URL res  = classLoader.getResource("jdbc.properties");
 30             String path = res.getPath();
 31            // System.out.println(path);///D:/IdeaProjects/itcast/out/production/day04_jdbc/jdbc.properties
 32             //2. 加载文件
 33            // pro.load(new FileReader("D:\IdeaProjects\itcast\day04_jdbc\src\jdbc.properties"));
 34             pro.load(new FileReader(path));
 35 
 36             //3. 获取数据,赋值
 37             url = pro.getProperty("url");
 38             user = pro.getProperty("user");
 39             password = pro.getProperty("password");
 40             driver = pro.getProperty("driver");
 41             //4. 注册驱动
 42             Class.forName(driver);
 43         } catch (IOException e) {
 44             e.printStackTrace();
 45         } catch (ClassNotFoundException e) {
 46             e.printStackTrace();
 47         }
 48     }
 49 
 50 
 51     /**
 52      * 获取连接
 53      * @return 连接对象
 54      */
 55     public static Connection getConnection() throws SQLException {
 56 
 57         return DriverManager.getConnection(url, user, password);
 58     }
 59 
 60     /**
 61      * 释放资源
 62      * @param stmt
 63      * @param conn
 64      */
 65     public static void close(Statement stmt,Connection conn){
 66         if( stmt != null){
 67             try {
 68                 stmt.close();
 69             } catch (SQLException e) {
 70                 e.printStackTrace();
 71             }
 72         }
 73 
 74         if( conn != null){
 75             try {
 76                 conn.close();
 77             } catch (SQLException e) {
 78                 e.printStackTrace();
 79             }
 80         }
 81     }
 82 
 83 
 84     /**
 85      * 释放资源
 86      * @param stmt
 87      * @param conn
 88      */
 89     public static void close(ResultSet rs,Statement stmt, Connection conn){
 90         if( rs != null){
 91             try {
 92                 rs.close();
 93             } catch (SQLException e) {
 94                 e.printStackTrace();
 95             }
 96         }
 97 
 98         if( stmt != null){
 99             try {
100                 stmt.close();
101             } catch (SQLException e) {
102                 e.printStackTrace();
103             }
104         }
105 
106         if( conn != null){
107             try {
108                 conn.close();
109             } catch (SQLException e) {
110                 e.printStackTrace();
111             }
112         }
113     }
114 
115 }

SQL注入

sql注入问题:普通的字符被当做语句执行,导致系统被通过等安全问题(如密码为:a' ='a' or 'a' ='a)。使用PreparedStatement对象处理,参数使用占位符替代(?),防止注入。 使用如下:即可。适合增删改查,效率更高。

代码语言:javascript复制
  1 package cn.itcast.jdbc;
  2 
  3 import cn.itcast.util.JDBCUtils;
  4 
  5 import java.sql.*;
  6 import java.util.Scanner;
  7 
  8 /**
  9  * 练习:
 10  *         * 需求:
 11  *             1. 通过键盘录入用户名和密码
 12  *             2. 判断用户是否登录成功
 13  */
 14 public class JDBCDemo9 {
 15 
 16     public static void main(String[] args) {
 17         //1.键盘录入,接受用户名和密码
 18         Scanner sc = new Scanner(System.in);
 19         System.out.println("请输入用户名:");
 20         String username = sc.nextLine();
 21         System.out.println("请输入密码:");
 22         String password = sc.nextLine();
 23         //2.调用方法
 24         boolean flag = new JDBCDemo9().login2(username, password);
 25         //3.判断结果,输出不同语句
 26         if(flag){
 27             //登录成功
 28             System.out.println("登录成功!");
 29         }else{
 30             System.out.println("用户名或密码错误!");
 31         }
 32 
 33 
 34     }
 35 
 36 
 37 
 38     /**
 39      * 登录方法
 40      */
 41     public boolean login(String username ,String password){
 42         if(username == null || password == null){
 43             return false;
 44         }
 45         //连接数据库判断是否登录成功
 46         Connection conn = null;
 47         Statement stmt =  null;
 48         ResultSet rs = null;
 49         //1.获取连接
 50         try {
 51             conn =  JDBCUtils.getConnection();
 52             //2.定义sql
 53             String sql = "select * from user where username = '" username "' and password = '" password "' ";
 54             System.out.println(sql);
 55             //3.获取执行sql的对象
 56             stmt = conn.createStatement();
 57             //4.执行查询
 58             rs = stmt.executeQuery(sql);
 59             //5.判断
 60            /* if(rs.next()){//如果有下一行,则返回true
 61                 return true;
 62             }else{
 63                 return false;
 64             }*/
 65            return rs.next();//如果有下一行,则返回true
 66 
 67         } catch (SQLException e) {
 68             e.printStackTrace();
 69         }finally {
 70             JDBCUtils.close(rs,stmt,conn);
 71         }
 72 
 73 
 74         return false;
 75     }
 76 
 77     /**
 78      * 登录方法,使用PreparedStatement实现
 79      */
 80     public boolean login2(String username ,String password){
 81         if(username == null || password == null){
 82             return false;
 83         }
 84         //连接数据库判断是否登录成功
 85         Connection conn = null;
 86         PreparedStatement pstmt =  null;
 87         ResultSet rs = null;
 88         //1.获取连接
 89         try {
 90             conn =  JDBCUtils.getConnection();
 91             //2.定义sql
 92             String sql = "select * from user where username = ? and password = ?";
 93             //3.获取执行sql的对象
 94             pstmt = conn.prepareStatement(sql);
 95             //给?赋值
 96             pstmt.setString(1,username);
 97             pstmt.setString(2,password);
 98             //4.执行查询,不需要传递sql
 99             rs = pstmt.executeQuery();
100             //5.判断
101            /* if(rs.next()){//如果有下一行,则返回true
102                 return true;
103             }else{
104                 return false;
105             }*/
106             return rs.next();//如果有下一行,则返回true
107 
108         } catch (SQLException e) {
109             e.printStackTrace();
110         }finally {
111             JDBCUtils.close(rs,pstmt,conn);
112         }
113 
114 
115         return false;
116     }
117 
118 
119 }

JDBC控制事务:使用Connection对象管理事务。开启(conn.setAutoCommit),提交(conn.commit),回滚(conn.rollback)。(见代码如下)

代码语言:javascript复制
 1 package cn.itcast.jdbc;
 2 
 3 import cn.itcast.util.JDBCUtils;
 4 
 5 import java.sql.Connection;
 6 import java.sql.PreparedStatement;
 7 import java.sql.SQLException;
 8 
 9 /**
10  * 事务操作
11  */
12 public class JDBCDemo10 {
13 
14 
15     public static void main(String[] args) {
16         Connection conn = null;
17         PreparedStatement pstmt1 = null;
18         PreparedStatement pstmt2 = null;
19 
20         try {
21             //1.获取连接
22             conn = JDBCUtils.getConnection();
23             //开启事务
24             conn.setAutoCommit(false);
25 
26             //2.定义sql
27             //2.1 张三 - 500
28             String sql1 = "update account set balance = balance - ? where id = ?";
29             //2.2 李四   500
30             String sql2 = "update account set balance = balance   ? where id = ?";
31             //3.获取执行sql对象
32             pstmt1 = conn.prepareStatement(sql1);
33             pstmt2 = conn.prepareStatement(sql2);
34             //4. 设置参数
35             pstmt1.setDouble(1,500);
36             pstmt1.setInt(2,1);
37 
38             pstmt2.setDouble(1,500);
39             pstmt2.setInt(2,2);
40             //5.执行sql
41             pstmt1.executeUpdate();
42             // 手动制造异常
43             int i = 3/0;
44 
45             pstmt2.executeUpdate();
46             //提交事务
47             conn.commit();
48         } catch (Exception e) {
49             //事务回滚
50             try {
51                 if(conn != null) {
52                     conn.rollback();
53                 }
54             } catch (SQLException e1) {
55                 e1.printStackTrace();
56             }
57             e.printStackTrace();
58         }finally {
59             JDBCUtils.close(pstmt1,conn);
60             JDBCUtils.close(pstmt2,null);
61         }
62 
63 
64     }
65 
66 }

数据库连接池

数据库连接池,解决连接和释放的效率低下问题(从容器(不是底层系统)中获取连接和释放)。 DateSource(sql下)接口,对应数据库的连接池,getConnection获取数据库连接对象。连接池技术如C3P0、Druid。归还连接:Connection.close不变。 导入对应的技术jar包,定义配置文件(c3p0.properties/c3p0-config.xml)在src目录下(定义连接参数,初始化数量),创建对象ComboPooledDateSource(传入参数或使用默认参数),然后获取连接等,相同(代码如下)。

代码语言:javascript复制
 1 package cn.itcast.datasource.c3p0;
 2 
 3 import com.mchange.v2.c3p0.ComboPooledDataSource;
 4 
 5 import javax.sql.DataSource;
 6 import java.sql.Connection;
 7 import java.sql.SQLException;
 8 
 9 /**
10  * c3p0演示
11  */
12 public class C3P0Demo2 {
13 
14     public static void main(String[] args) throws SQLException {
15        /* //1. 获取DataSource,使用默认配置
16         DataSource ds  = new ComboPooledDataSource();
17 
18         //2.获取连接
19 
20         for (int i = 1; i <= 11 ; i  ) {
21             Connection conn = ds.getConnection();
22             System.out.println(i ":" conn);
23 
24             if(i == 5){
25                 conn.close();//归还连接到连接池中
26             }
27         }*/
28 
29         //testNamedConfig();
30 
31     }
32 
33 
34     public static void testNamedConfig() throws SQLException {
35         // 1.1 获取DataSource,使用指定名称配置
36         DataSource ds  = new ComboPooledDataSource("otherc3p0");
37         //2.获取连接
38         for (int i = 1; i <= 10 ; i  ) {
39             Connection conn = ds.getConnection();
40             System.out.println(i ":" conn);
41         }
42     }
43 
44 }

Druid使用DruidDataSourceFactory创建对象,使用createDataSource获取连接对象。定义工具类,写好静态代码块,方便使用。(代码如下,),对应使用的配置文件为druid.properties

代码语言:javascript复制
 1 package cn.itcast.datasource.druid;
 2 
 3 import cn.itcast.utils.JDBCUtils;
 4 
 5 import java.sql.Connection;
 6 import java.sql.PreparedStatement;
 7 import java.sql.ResultSet;
 8 import java.sql.SQLException;
 9 
10 /**
11  * 使用新的工具类
12  */
13 public class DruidDemo2 {
14 
15     public static void main(String[] args) {
16         /*
17          * 完成添加操作:给account表添加一条记录
18          */
19         Connection conn = null;
20         PreparedStatement pstmt = null;
21         try {
22             //1.获取连接
23             conn = JDBCUtils.getConnection();
24             //2.定义sql
25             String sql = "insert into account values(null,?,?)";
26             //3.获取pstmt对象
27             pstmt = conn.prepareStatement(sql);
28             //4.给?赋值
29             pstmt.setString(1,"王五");
30             pstmt.setDouble(2,3000);
31             //5.执行sql
32             int count = pstmt.executeUpdate();
33             System.out.println(count);
34         } catch (SQLException e) {
35             e.printStackTrace();
36         }finally {
37             //6. 释放资源
38             JDBCUtils.close(pstmt,conn);
39         }
40     }
41 
42 }

工具类

代码语言:javascript复制
  1 package cn.itcast.utils;
  2 
  3 import com.alibaba.druid.pool.DruidDataSourceFactory;
  4 
  5 import javax.sql.DataSource;
  6 import java.io.IOException;
  7 import java.sql.Connection;
  8 import java.sql.ResultSet;
  9 import java.sql.SQLException;
 10 import java.sql.Statement;
 11 import java.util.Properties;
 12 
 13 /**
 14  * Druid连接池的工具类
 15  */
 16 public class JDBCUtils {
 17 
 18     //1.定义成员变量 DataSource
 19     private static DataSource ds ;
 20 
 21     static{
 22         try {
 23             //1.加载配置文件
 24             Properties pro = new Properties();
 25             pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
 26             //2.获取DataSource
 27             ds = DruidDataSourceFactory.createDataSource(pro);
 28         } catch (IOException e) {
 29             e.printStackTrace();
 30         } catch (Exception e) {
 31             e.printStackTrace();
 32         }
 33     }
 34 
 35     /**
 36      * 获取连接
 37      */
 38     public static Connection getConnection() throws SQLException {
 39         return ds.getConnection();
 40     }
 41 
 42     /**
 43      * 释放资源
 44      */
 45     public static void close(Statement stmt,Connection conn){
 46        /* if(stmt != null){
 47             try {
 48                 stmt.close();
 49             } catch (SQLException e) {
 50                 e.printStackTrace();
 51             }
 52         }
 53 
 54         if(conn != null){
 55             try {
 56                 conn.close();//归还连接
 57             } catch (SQLException e) {
 58                 e.printStackTrace();
 59             }
 60         }*/
 61 
 62        close(null,stmt,conn);
 63     }
 64 
 65 
 66     public static void close(ResultSet rs , Statement stmt, Connection conn){
 67 
 68 
 69         if(rs != null){
 70             try {
 71                 rs.close();
 72             } catch (SQLException e) {
 73                 e.printStackTrace();
 74             }
 75         }
 76 
 77 
 78         if(stmt != null){
 79             try {
 80                 stmt.close();
 81             } catch (SQLException e) {
 82                 e.printStackTrace();
 83             }
 84         }
 85 
 86         if(conn != null){
 87             try {
 88                 conn.close();//归还连接
 89             } catch (SQLException e) {
 90                 e.printStackTrace();
 91             }
 92         }
 93     }
 94 
 95     /**
 96      * 获取连接池方法
 97      */
 98 
 99     public static DataSource getDataSource(){
100         return  ds;
101     }
102 
103 }

Spring JDBC

Spring JDBC(Spring对JDBC的简单封装)。导入jar包,创建JdbcTemplate对象,调用update执行DML,queryForMap封装为map,queryForList封装为list,query封装为JavaBean,queryForObject封装为对象。 (代码)

代码语言:javascript复制
 1 package cn.itcast.jdbctemplate;
 2 
 3 import cn.itcast.utils.JDBCUtils;
 4 import org.springframework.jdbc.core.JdbcTemplate;
 5 
 6 /**
 7  * JdbcTemplate入门
 8  */
 9 public class JdbcTemplateDemo1 {
10 
11     public static void main(String[] args) {
12         //1.导入jar包
13         //2.创建JDBCTemplate对象
14         JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
15         //3.调用方法
16         String sql = "update account set balance = 5000 where id = ?";
17         int count = template.update(sql, 3);
18         System.out.println(count);
19     }
20 }

单元测试

代码语言:javascript复制
  1 package cn.itcast.jdbctemplate;
  2 
  3 import cn.itcast.domain.Emp;
  4 import cn.itcast.utils.JDBCUtils;
  5 import org.junit.Test;
  6 import org.springframework.jdbc.core.BeanPropertyRowMapper;
  7 import org.springframework.jdbc.core.JdbcTemplate;
  8 import org.springframework.jdbc.core.RowMapper;
  9 
 10 import java.sql.Date;
 11 import java.sql.ResultSet;
 12 import java.sql.SQLException;
 13 import java.util.List;
 14 import java.util.Map;
 15 
 16 public class JdbcTemplateDemo2 {
 17 
 18     //Junit单元测试,可以让方法独立执行
 19 
 20 
 21     //1. 获取JDBCTemplate对象
 22     private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
 23     /**
 24      * 1. 修改1号数据的 salary 为 10000
 25      */
 26     @Test
 27     public void test1(){
 28 
 29         //2. 定义sql
 30         String sql = "update emp set salary = 10000 where id = 1001";
 31         //3. 执行sql
 32         int count = template.update(sql);
 33         System.out.println(count);
 34     }
 35 
 36     /**
 37      * 2. 添加一条记录
 38      */
 39     @Test
 40     public void test2(){
 41         String sql = "insert into emp(id,ename,dept_id) values(?,?,?)";
 42         int count = template.update(sql, 1015, "郭靖", 10);
 43         System.out.println(count);
 44 
 45     }
 46 
 47     /**
 48      * 3.删除刚才添加的记录
 49      */
 50     @Test
 51     public void test3(){
 52         String sql = "delete from emp where id = ?";
 53         int count = template.update(sql, 1015);
 54         System.out.println(count);
 55     }
 56 
 57     /**
 58      * 4.查询id为1001的记录,将其封装为Map集合
 59      * 注意:这个方法查询的结果集长度只能是1
 60      */
 61     @Test
 62     public void test4(){
 63         String sql = "select * from emp where id = ? or id = ?";
 64         Map<String, Object> map = template.queryForMap(sql, 1001,1002);
 65         System.out.println(map);
 66         //{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}
 67 
 68     }
 69 
 70     /**
 71      * 5. 查询所有记录,将其封装为List
 72      */
 73     @Test
 74     public void test5(){
 75         String sql = "select * from emp";
 76         List<Map<String, Object>> list = template.queryForList(sql);
 77 
 78         for (Map<String, Object> stringObjectMap : list) {
 79             System.out.println(stringObjectMap);
 80         }
 81     }
 82 
 83     /**
 84      * 6. 查询所有记录,将其封装为Emp对象的List集合
 85      */
 86 
 87     @Test
 88     public void test6(){
 89         String sql = "select * from emp";
 90         List<Emp> list = template.query(sql, new RowMapper<Emp>() {
 91 
 92             @Override
 93             public Emp mapRow(ResultSet rs, int i) throws SQLException {
 94                 Emp emp = new Emp();
 95                 int id = rs.getInt("id");
 96                 String ename = rs.getString("ename");
 97                 int job_id = rs.getInt("job_id");
 98                 int mgr = rs.getInt("mgr");
 99                 Date joindate = rs.getDate("joindate");
100                 double salary = rs.getDouble("salary");
101                 double bonus = rs.getDouble("bonus");
102                 int dept_id = rs.getInt("dept_id");
103 
104                 emp.setId(id);
105                 emp.setEname(ename);
106                 emp.setJob_id(job_id);
107                 emp.setMgr(mgr);
108                 emp.setJoindate(joindate);
109                 emp.setSalary(salary);
110                 emp.setBonus(bonus);
111                 emp.setDept_id(dept_id);
112 
113                 return emp;
114             }
115         });
116 
117 
118         for (Emp emp : list) {
119             System.out.println(emp);
120         }
121     }
122 
123     /**
124      * 6. 查询所有记录,将其封装为Emp对象的List集合
125      */
126 
127     @Test
128     public void test6_2(){
129         String sql = "select * from emp";
130         List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
131         for (Emp emp : list) {
132             System.out.println(emp);
133         }
134     }
135 
136     /**
137      * 7. 查询总记录数
138      */
139 
140     @Test
141     public void test7(){
142         String sql = "select count(id) from emp";
143         Long total = template.queryForObject(sql, Long.class);
144         System.out.println(total);
145     }
146 
147 }

附件

代码语言:javascript复制
 1 package cn.itcast.domain;
 2 
 3 import java.util.Date;
 4 
 5 public class Emp {
 6     private Integer id;
 7     private String ename;
 8     private Integer job_id;
 9     private Integer mgr;
10     private Date joindate;
11     private Double salary;
12     private Double bonus;
13     private Integer dept_id;
14 
15 
16     public Integer getId() {
17         return id;
18     }
19 
20     public void setId(Integer id) {
21         this.id = id;
22     }
23 
24     public String getEname() {
25         return ename;
26     }
27 
28     public void setEname(String ename) {
29         this.ename = ename;
30     }
31 
32     public Integer getJob_id() {
33         return job_id;
34     }
35 
36     public void setJob_id(Integer job_id) {
37         this.job_id = job_id;
38     }
39 
40     public Integer getMgr() {
41         return mgr;
42     }
43 
44     public void setMgr(Integer mgr) {
45         this.mgr = mgr;
46     }
47 
48     public Date getJoindate() {
49         return joindate;
50     }
51 
52     public void setJoindate(Date joindate) {
53         this.joindate = joindate;
54     }
55 
56     public Double getSalary() {
57         return salary;
58     }
59 
60     public void setSalary(Double salary) {
61         this.salary = salary;
62     }
63 
64     public Double getBonus() {
65         return bonus;
66     }
67 
68     public void setBonus(Double bonus) {
69         this.bonus = bonus;
70     }
71 
72     public Integer getDept_id() {
73         return dept_id;
74     }
75 
76     public void setDept_id(Integer dept_id) {
77         this.dept_id = dept_id;
78     }
79 
80     @Override
81     public String toString() {
82         return "Emp{"  
83                 "id="   id  
84                 ", ename='"   ename   '''  
85                 ", job_id="   job_id  
86                 ", mgr="   mgr  
87                 ", joindate="   joindate  
88                 ", salary="   salary  
89                 ", bonus="   bonus  
90                 ", dept_id="   dept_id  
91                 '}';
92     }
93 }

0 人点赞