jdbc-增强

MySQL执行预编译分为如三步:1、执行预编译语句;2.设置变量;3.执行语句

如果需要再次执行,那么就不再需要第一步,即不需要再编译语句了:1.设置变量;2.执行语句;

防sql注入

public class Demo {

    private String name = "ericdfd' OR 1=1 -- ";
    //private String name = "eric";
    private String password = "123456";

    /**
     * Statment存在sql被注入的风险
     */
    @Test
    public void testByStatement(){
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtil.getConnection();
            stmt = conn.createStatement();
            String sql = "SELECT * FROM user WHERE NAME='"+name+"' AND PASSWORD='"+password+"'";
            rs = stmt.executeQuery(sql);
            if(rs.next()){
                System.out.println("登录成功");
            }else{
                System.out.println("登录失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            JdbcUtil.close(conn, stmt ,rs);
        }
    }

    /**
     * PreparedStatement可以有效地防止sql被注入
     */
    @Test
    public void testByPreparedStatement(){
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtil.getConnection();
            String sql = "SELECT * FROM user WHERE NAME=? AND PASSWORD=?";
            stmt = conn.prepareStatement(sql);
            stmt.setString(1, name);
            stmt.setString(2, password);
            rs = stmt.executeQuery();
            if(rs.next()){
                System.out.println("登录成功");
            }else{
                System.out.println("登录失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            JdbcUtil.close(conn, stmt ,rs);
        }
    }
}

批处理

public class Admin {

    private String userName;
    private String pwd;

    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
    
}
public class AdminDao {

    private Connection con;
    private PreparedStatement pstmt;
    private ResultSet rs;

    public void save(List<Admin> list) {
        String sql = "INSERT INTO admin(userName,pwd) values(?,?)";
        try {
            con = JdbcUtil.getConnection();
            pstmt = con.prepareStatement(sql);
            for (int i=0; i<list.size(); i++) {
                Admin admin = list.get(i);
                pstmt.setString(1, admin.getUserName());
                pstmt.setString(2, admin.getPwd());
                pstmt.addBatch();
                if (i % 5 == 0) {
                    pstmt.executeBatch();
                    pstmt.clearBatch();
                }
            }
            pstmt.executeBatch();
            pstmt.clearBatch();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.close(con, pstmt, rs);
        }
    }
}
public class App {

    @Test
    public void testBatch() throws Exception {

        List<Admin> list = new ArrayList<>();
        for (int i=1; i<21; i++) {
            Admin admin = new Admin();
            admin.setUserName("Jack" + i);
            admin.setPwd("888" + i);
            list.add(admin);
        }
        AdminDao dao = new AdminDao();
        dao.save(list);
    }
}

 Jdbc事务

在默认情况下,每执行一条SQL语句,都是一个单独的事务。如果需要在一个事务中包含多条SQL语句,那么需要开启事务和结束事务。

在执行SQL语句之前,先执行strat transaction,这就开启了一个事务(事务的起点),然后可以去执行多条SQL语句,最后要结束事务,commit表示提交,即事务中的多条SQL语句所做出的影响会持久化到数据库中。或者rollback,表示回滚,即回滚到事务的起点,之前做的所有操作都被撤消了。

Connection的三个方法与事务相关:

(1)setAutoCommit(boolean):设置是否为自动提交事务,如果true(默认值就是true)表示自动提交,也就是每条执行的SQL语句都是一个单独的事务。

          如果设置false,那么就相当于开启了事务了;con.setAutoCommit(false)表示开启事务。

(2)commit():提交结束事务;con.commit();表示提交事务。

(3)rollback():回滚结束事务。con.rollback();表示回滚事务。

public class TransAccount {

    // 全局参数
    private Connection con;
    private PreparedStatement pstmt;

    // 1. 转账,没有使用事务
    @Test
    public void trans() {

        String sql_zs = "UPDATE account SET money=money-1000 WHERE account_name ='张三';";
        String sql_ls = "UPDATE account SET money1=money+1000 WHERE account_name='李四';";
        try {
            con = JdbcUtil.getConnection();
            //con.setAutoCommit(true);
            /*** 第一次执行SQL ***/
            pstmt = con.prepareStatement(sql_zs);
            pstmt.executeUpdate();
            /*** 第二次执行SQL ***/
            pstmt = con.prepareStatement(sql_ls);
            pstmt.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.close(con, pstmt);
        }
    }

    // 2. 转账,使用事务
    @Test
    public void trans2() {

        String sql_zs = "UPDATE account SET money=money-1000 WHERE account_name='张三'";
        String sql_ls = "UPDATE account SET money=money+1000 WHERE account_name ='李四'";
        try {
            con = JdbcUtil.getConnection();
            // 设置事务为手动提交
            con.setAutoCommit(false);
            /*** 第一次执行SQL ***/
            pstmt = con.prepareStatement(sql_zs);
            pstmt.executeUpdate();
            /*** 第二次执行SQL ***/
            pstmt = con.prepareStatement(sql_ls);
            pstmt.executeUpdate();
        } catch (Exception e) {
            try {
                // 出现异常,需要回滚事务
                con.rollback();
            } catch (SQLException e1) {
            }
            e.printStackTrace();
        } finally {
            try {
                // 所有的操作执行成功, 提交事务
                con.commit();
                JdbcUtil.close(con, pstmt);
            } catch (SQLException e) {
            }
        }
    }

    // 3. 转账,使用事务, 回滚到指定的代码段
    @Test
    public void trans3() {
        // 定义个标记
        Savepoint sp = null;
        // 第一次转账
        String sql_zs1 = "UPDATE account SET money=money-1000 WHERE account_name ='张三';";
        String sql_ls1 = "UPDATE account SET money=money+1000 WHERE account_name ='李四';";
        // 第二次转账
        String sql_zs2 = "UPDATE account SET money=money-500 WHERE account_name ='张三';";
        String sql_ls2 = "UPDATE1 account SET money=money+500 WHERE account_name ='李四';";
        try {
            con = JdbcUtil.getConnection(); // 默认开启的隐士事务
            con.setAutoCommit(false);       // 设置事务手动提交
            /*** 第一次转账 ***/
            pstmt = con.prepareStatement(sql_zs1);
            pstmt.executeUpdate();
            pstmt = con.prepareStatement(sql_ls1);
            pstmt.executeUpdate();
            // 回滚到这个位置?
            sp = con.setSavepoint();
            /*** 第二次转账 ***/
            pstmt = con.prepareStatement(sql_zs2);
            pstmt.executeUpdate();
            pstmt = con.prepareStatement(sql_ls2);
            pstmt.executeUpdate();
        } catch (Exception e) {
            try {
                // 回滚 (回滚到指定的代码段)
                con.rollback(sp);
            } catch (SQLException e1) {
            }
            e.printStackTrace();
        } finally {
            try {
                // 提交
                con.commit();
            } catch (SQLException e) {
            }
            JdbcUtil.close(con, pstmt);
        }
    }

}

 BeanUtils组件

 1 public class Admin {
 2 
 3     private int id;
 4     private String userName;
 5     private int age;
 6 
 7     public int getId() {
 8         return id;
 9     }
10     public void setId(int id) {
11         this.id = id;
12     }
13     public String getUserName() {
14         return userName;
15     }
16     public void setUserName(String userName) {
17         this.userName = userName;
18     }
19     public int getAge() {
20         return age;
21     }
22     public void setAge(int age) {
23         this.age = age;
24     }
25 
26     @Override
27     public String toString() {
28         return "Admin{" +
29                 "id=" + id +
30                 ", userName='" + userName + '\'' +
31                 ", age=" + age +
32                 '}';
33     }
34 }
View Code
 1 public class App {
 2 
 3     @Test
 4     public void test() throws Exception {
 5 
 6         Admin admin = new Admin();
 7         // 对象属性的拷贝
 8         BeanUtils.copyProperty(admin, "userName", "jack");
 9         BeanUtils.setProperty(admin, "age", 18);
10         System.out.println(admin.toString());
11 
12         // 对象之间的拷贝
13         Admin newAdmin = new Admin();
14         BeanUtils.copyProperties(newAdmin, admin);
15         System.out.println(newAdmin.toString());
16 
17         // Map数据拷贝到对象
18         Admin adminMap = new Admin();
19         Map<String,Object> map = new HashMap<>();
20         map.put("userName", "Jerry");
21         map.put("age", 29);
22         BeanUtils.populate(adminMap, map);
23         System.out.println(adminMap.toString());
24 
25     }
26 }

 元数据

元数据:数据库、表、列的定义信息。

DataBaseMetaData对象:Connection.getMetaData() 获得代表Connection元数据的DataBaseMetaData对象。

常用方法:

getURL():返回一个String类对象,代表数据库的URL

getUserName():返回连接当前数据库管理系统的用户名

getDatabaseProductName():返回数据库的产品名称

getDatabaseProductVersion():返回数据库的版本号

getDriverName():返回驱动驱动程序的名称

getDriverVersion():返回驱动程序的版本号

isReadOnly():返回一个boolean值,指示数据库是否只允许读操作

ParameterMetaData对象:PreparedStatement.getParameterMetaData()获得代表PreparedStatement元数据的ParameterMetaData对象

常用方法:

getParameterCount() 获得指定参数的个数

getParameterType(int param) 获得指定参数的sql类型

ResultSetMetaData对象:ResultSet.getMetaData()获得代表ResultSet对象元数据的ResultSetMetaData对象

常用方法:

getColumnCount() 返回resultset对象的列数

getColumnName(int column) 获得指定列的名称  

getColumnTypeName(int column) 获得指定列的类型

 1 public class App {
 2 
 3     // 1. 数据库元数据
 4     @Test
 5     public void testDB() throws Exception {
 6 
 7         Connection conn = JdbcUtil.getConnection();
 8         // 获取数据库元数据
 9         DatabaseMetaData metaData = conn.getMetaData();
10         System.out.println(metaData.getUserName());
11         System.out.println(metaData.getURL());
12         System.out.println(metaData.getDatabaseProductName());
13     }
14 
15     // 2. 参数元数据
16     @Test
17     public void testParams() throws Exception {
18 
19         Connection conn = JdbcUtil.getConnection();
20         String sql = "select * from account where account_name=?";
21         PreparedStatement pstmt = conn.prepareStatement(sql);
22         // 参数元数据
23         ParameterMetaData metaDate = pstmt.getParameterMetaData();
24         // 获取参数的个数
25         int count = metaDate.getParameterCount();
26         System.out.println(count);
27     }
28 
29     //  3. 结果集元数据
30     @Test
31     public void testRs() throws Exception {
32         String sql = "select * from account ";
33         Connection conn = JdbcUtil.getConnection();
34         PreparedStatement pstmt = conn.prepareStatement(sql);
35         ResultSet rs = pstmt.executeQuery();
36         // 得到结果集元数据(目标:通过结果集元数据,得到列的名称)
37         ResultSetMetaData metaData = rs.getMetaData();
38         while (rs.next()) {
39             // 获取列的个数
40             int count = metaData.getColumnCount();
41             // 遍历,获取每一列的列的名称
42             for (int i=0; i<count; i++) {
43                 // 得到列的名称
44                 String columnName = metaData.getColumnName(i + 1);
45                 // 获取每一行的每一列的值
46                 Object columnValue = rs.getObject(columnName);
47                 System.out.print(columnName + "=" + columnValue + ",");
48             }
49             System.out.println();
50         }
51     }
52 }
 1 public class Admin {
 2 
 3     private int id;
 4     private String username;
 5     private String pwd;
 6 
 7     public String getPwd() {
 8         return pwd;
 9     }
10     public void setPwd(String pwd) {
11         this.pwd = pwd;
12     }
13     public int getId() {
14         return id;
15     }
16     public void setId(int id) {
17         this.id = id;
18     }
19     public String getUsername() {
20         return username;
21     }
22     public void setUsername(String username) {
23         this.username = username;
24     }
25     @Override
26     public String toString() {
27         return "Admin [id=" + id + ", pwd=" + pwd + ", username=" + username
28                 + "]";
29     }
30 }
View Code
 1 public class BaseDao {
 2 
 3     // 初始化参数
 4     private Connection con;
 5     private PreparedStatement pstmt;
 6     private ResultSet rs;
 7 
 8     /**
 9      * 更新的通用方法
10      */
11     public void update(String sql,Object[] paramsValue){
12 
13         try {
14             con = JdbcUtil.getConnection();
15             pstmt = con.prepareStatement(sql);
16             int count = pstmt.getParameterMetaData().getParameterCount();
17             if (paramsValue != null && paramsValue.length > 0) {
18                 for(int i=0;i<count;i++) {
19                     pstmt.setObject(i+1, paramsValue[i]);
20                 }
21             }
22             pstmt.executeUpdate();
23         } catch (Exception e) {
24             throw new RuntimeException(e);
25         } finally {
26             JdbcUtil.close(con, pstmt);
27         }
28     }
29 
30     /**
31      * 查询的通用方法
32      */
33     public <T> List<T> query(String sql, Object[] paramsValue, Class<T> clazz){
34 
35         try {
36             List<T> list = new ArrayList<>();
37             T t;
38             con = JdbcUtil.getConnection();
39             pstmt = con.prepareStatement(sql);
40             if (paramsValue != null && paramsValue.length > 0) {
41                 for (int i=0; i<paramsValue.length; i++) {
42                     pstmt.setObject(i+1, paramsValue[i]);
43                 }
44             }
45             rs = pstmt.executeQuery();
46             ResultSetMetaData rsmd = rs.getMetaData();
47             int columnCount = rsmd.getColumnCount();
48             while (rs.next()) {
49                 t = clazz.newInstance();
50                 for (int i=0; i<columnCount; i++) {
51                     String columnName = rsmd.getColumnName(i + 1);
52                     Object value = rs.getObject(columnName);
53                     BeanUtils.copyProperty(t, columnName, value);
54                 }
55                 list.add(t);
56             }
57             return list;
58         } catch (Exception e) {
59             throw new RuntimeException(e);
60         } finally {
61             JdbcUtil.close(con, pstmt, rs);
62         }
63     }
64 }
View Code
 1 public class AdminDao extends BaseDao {
 2 
 3     // 删除
 4     public void delete(int id) {
 5         String sql = "delete from admin where id=?";
 6         Object[] paramsValue = {id};
 7         super.update(sql, paramsValue);
 8     }
 9 
10     // 插入
11     public void save(Admin admin) {
12         String sql = "insert into admin (userName,pwd) values (?,?)";
13         Object[] paramsValue = {admin.getUsername(),admin.getPwd()};
14         super.update(sql, paramsValue);
15     }
16 
17     // 查询全部
18     public List<Admin> getAll(){
19         String sql = "select * from admin";
20         List<Admin> list = super.query(sql, null, Admin.class);
21         return list;
22     }
23 
24     // 根据条件查询(主键)
25     public Admin findById(int id){
26         String sql = "select * from admin where id=?";
27         List<Admin> list = super.query(sql, new Object[]{id}, Admin.class);
28         return  (list!=null&&list.size()>0) ? list.get(0) : null;
29     }
30 }
View Code
 1 public class MainTest {
 2 
 3     @Test
 4     public void testUpdate() throws Exception {
 5         AdminDao adminDao = new AdminDao();
 6         adminDao.delete(2);
 7         Admin admin = new Admin();
 8         admin.setUsername("test");
 9         admin.setPwd("test");
10         adminDao.save(admin);
11     }
12 
13     @Test
14     public void testQuery() throws Exception {
15         AdminDao adminDao = new AdminDao();
16         List<Admin> list = adminDao.getAll();
17         System.out.println(list);
18         Admin admin = adminDao.findById(3);
19         System.out.println(admin);
20     }
21 }
View Code

 

posted @ 2018-11-11 21:51  过向往的生活  阅读(272)  评论(0编辑  收藏  举报