JDBC 程序编写
1.大致流程

2.创建数据库连接的五种方式
import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; import org.junit.Test; public class ConnectionTest { //方式一 @Test public void testConnection1() throws SQLException { //获取Driver的实现类对象 Driver driver = new com.mysql.jdbc.Driver(); //获取连接参数 String url = "jdbc:mysql://localhost:3306/test"; Properties info = new Properties(); info.setProperty("user","root"); info.setProperty("password", "root@123"); //获取连接实例 Connection conn = driver.connect(url, info); System.out.println(conn); } //方式二,对方式一的迭代:在如下的程序中不出现第三方的API,使得程序具有更好的可移植性 @Test public void testConnection2() throws Exception{ //1.获取Driver的实现类对象 Class clazz = Class.forName("com.mysql.jdbc.Driver"); Driver driver = (Driver) clazz.newInstance(); //2.提供要连接的数据库 String url = "jdbc:mysql://localhost:3306/test"; //3.提供连接需要的用户名和密码 Properties info = new Properties(); info.setProperty("user","root"); info.setProperty("password", "root@123"); //4.获取链接 Connection conn = driver.connect(url, info); System.out.println(conn); } //方式三,使用DriverManager替换Driver @Test public void testConnection3() throws Exception { //1.获取Driver实现类的对象 Class clazz = Class.forName("com.mysql.jdbc.Driver"); Driver driver = (Driver) clazz.newInstance(); //2.提供另外三个连接的基本信息 String url = "jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "root@123"; //3.获取链接 //注册驱动 DriverManager.registerDriver(driver); //获取链接 Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); } //方式四,可以只是加载驱动,不用显式地注册驱动了 @Test public void testConnection4() throws Exception { //1.提供三个连接的基本信息 String url = "jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "root@123"; //2.加载Driver Class.forName("com.mysql.jdbc.Driver"); //相较于方式三可以省略如下的操作 // Driver driver = (Driver) clazz.newInstance(); // //注册驱动 // DriverManager.registerDriver(driver); //为什么可以省略上述操作呢 /* * 在mysql的Driver实现类中,声明了注册驱动的静态代码块 * */ //3.获取链接 Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); } //方式五(final版):将数据库连接需要的4个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接 /* * 此种方式的好处? * 1.实现了数据与代码的分离,实现了解耦 * 2.如果需要修改配置文件信息,可以避免程序重新打包 */ @Test public void testConnection5() throws Exception { //1.读取配置文件中的四个基本信息 InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties"); Properties props = new Properties(); props.load(is); String user = props.getProperty("user"); String password = props.getProperty("password"); String url = props.getProperty("url"); String driver = props.getProperty("driver"); //2.加载驱动 Class.forName(driver); //3.获取连接 Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); } }
通用方法:获取链接以及关闭资源单独创建工具类
/* * 操作数据库的工具类 */ public class JDBCUtils { //获取数据库的连接 public static Connection getConnection() throws Exception { //1.读取配置文件中的四个基本信息 InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"); Properties props = new Properties(); props.load(is); String user = props.getProperty("user"); String password = props.getProperty("password"); String url = props.getProperty("url"); String driver = props.getProperty("driver"); //2.加载驱动 Class.forName(driver); //3.获取连接 Connection conn = DriverManager.getConnection(url, user, password); return conn; } //关闭资源的操作 public static void closeResource(Connection conn,PreparedStatement ps) { if(conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } if(ps != null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
通用的增删改操作
@Test public void testCommonUpdate() { // String sql = "delete from customers where id = ?"; // update(sql, 3); String sql = "update `order` set order_name = ? where order_id = ?"; update(sql, "DD","2"); } //通用的增删改操作 public void update(String sql,Object ...args){//sql中占位符的个数应该与可变形参长度一致 Connection conn = null; PreparedStatement ps = null; try { //1.获取数据库连接 conn = JDBCUtils.getConnection(); //2.预编译sql语句,返回PreparedStatement实例 ps = conn.prepareStatement(sql); //3.填充占位符 for(int i = 0;i < args.length;i++) { ps.setObject(i+1, args[i]); } //4.执行 ps.execute(); }catch (Exception e) { e.printStackTrace(); }finally { //5.关闭资源 JDBCUtils.closeResource(conn, ps); } }
* ORM编程思想(object relating mapping)
一个数据表对应一个Java类
表中的一条记录对应Java类的一个对象
表中的一个字段对应Java类的一个属性

/* * 针对order表的通用查询操作 */ public class OrderForQuery { /* * 针对表的字段名与类的属性名不相同的情况, * 1.必须声明sql时,使用类的属性名来命名字段的别名 * 2.使用ResultSetMetaData时,需要使用getColumnLabel()来替换getColumnName(), * 获取列的名。 * 说明:如果sql中没有给字段取别名,getColumnLabel()获取的就是列名 */ @Test public void testOrderQuery() { String sql = "select order_id,order_name,order_date from `order` where order_id = ? "; Order order = testOrderQuery(sql, 2); System.out.println(order); } public Order testOrderQuery(String sql,Object ...args){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { //建立数据库连接 conn = JDBCUtils.getConnection(); //预编辑sql语句,返回prepareStatement实例 ps = conn.prepareStatement(sql); //填充占位符 for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } //执行 ps.executeQuery(); //获取结果集 rs = ps.getResultSet(); //获取结果集的元数据 ResultSetMetaData rsmd = rs.getMetaData(); int columnCount = rsmd.getColumnCount(); if(rs.next()) { Order order = new Order(); //循环每一行 for (int i = 0; i < columnCount; i++) { //获取每一列的数据值 Object columnValue = rs.getObject(i + 1); //getColumnName 不推荐使用,建议使用getColumnLabel获取列名 String columnName = rsmd.getColumnName(i + 1); Field field = Order.class.getDeclaredField(columnName); field.setAccessible(true); field.set(order, columnValue); } return order; } }catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtils.closeResource(conn, ps, rs); } return null; } }
通用查询的流程:

通用查询终极版:
public class CommonQuery { @Test public void testGetForList() { String sql = "SELECT id,name,email,birth FROM customers WHERE id < ?"; List<Customer> list = getForList(Customer.class, sql, 12); list.forEach(System.out::println); String sql1 = "SELECT order_id,order_name,order_date FROM `order` WHERE order_id< ?"; List<Order> list1 = getForList(Order.class, sql1, 4); list1.forEach(System.out::println); } @Test public void testGetInstance() { String sql = "SELECT id,name,email,birth FROM customers WHERE id = ? "; Customer cust = getInstance(Customer.class, sql, 2); System.out.println(cust); } public <T> List<T> getForList(Class<T> clazz, String sql, Object ...args){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { //建立连接 conn = JDBCUtils.getConnection(); //预编辑sql语句,返回preparedStatement对象实例 ps = conn.prepareStatement(sql); //填充占位符 for (int i = 0; i < args.length; i++) { ps.setObject(i + 1 , args[i]); } //执行语句 rs = ps.executeQuery(); //获取元数据集 ResultSetMetaData rsmd = rs.getMetaData(); //通过元数据集获取列数 int columnCount = rsmd.getColumnCount(); //创建集合对象 ArrayList<T> list = new ArrayList<T>(); //判断是否有下一行并换行 while(rs.next()) { T t = clazz.newInstance(); for (int i = 0; i < columnCount; i++) { //通过结果集获取列值 Object columnValue = rs.getObject(i + 1); //通过元数据集获取列名 String columnLabel = rsmd.getColumnLabel(i + 1); //通过反射获取columnName属性,并为属性赋值为columnValue Field field = clazz.getDeclaredField(columnLabel); field.setAccessible(true); field.set(t, columnValue); } list.add(t); } return list; }catch (Exception e) { e.printStackTrace(); } return null; } public <T> T getInstance(Class<T> clazz, String sql, Object ...args){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { //建立连接 conn = JDBCUtils.getConnection(); //预编辑sql语句,返回preparedStatement对象实例 ps = conn.prepareStatement(sql); //填充占位符 for (int i = 0; i < args.length; i++) { ps.setObject(i + 1 , args[i]); } //执行语句 rs = ps.executeQuery(); //获取元数据集 ResultSetMetaData rsmd = rs.getMetaData(); //通过元数据集获取列数 int columnCount = rsmd.getColumnCount(); //判断是否有下一行并换行 while(rs.next()) { T t = clazz.newInstance(); for (int i = 0; i < columnCount; i++) { //通过结果集获取列值 Object columnValue = rs.getObject(i + 1); //通过元数据集获取列名 String columnLabel = rsmd.getColumnLabel(i + 1); //通过反射获取columnName属性,并为属性赋值为columnValue Field field = clazz.getDeclaredField(columnLabel); field.setAccessible(true); field.set(t, columnValue); } return t; } }catch (Exception e) { e.printStackTrace(); } return null; } }
Statement 和PrepareStatement
* 除了解决Statement的拼串导致的sql注入问题之外,PreparedStatement还有如下好处:
* 1.PreparedStatement操作Blob的数据,而Statement做不到。
* 2.PreparedStatement 可以实现更高效的批量操作。
批量插入:
1.
ps.addBatch();
ps.excuteBatch()
ps.clearbatch()
2.
setAutoCommit(false);
conn.commit();

浙公网安备 33010602011771号