说明
越来越晕了,教程和代码示范来自黑马程序员。用了再看吧。
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配置信息,通过类加载器动态获取绝对路径。

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对象处理,参数使用占位符替代(?),防止注入。
使用如下:即可。适合增删改查,效率更高。

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)。(见代码如下)

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(传入参数或使用默认参数),然后获取连接等,相同(代码如下)。

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

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 }
工具类

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封装为对象。
(代码)

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 }
单元测试

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 }
附件

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 }
来源:https://www.cnblogs.com/bai2018/p/12298548.html