当前位置: 首页 > news >正文

平面设计在线网站网站关键词用什么符号

平面设计在线网站,网站关键词用什么符号,wordpress 做购物网站,江浦做网站文章目录 一、引言1.1 如何操作数据库1.2 实际开发中#xff0c;会采用客户端操作数据库吗#xff1f; 二、JDBC#xff08;Java Database Connectivity#xff09;2.1 什么是 JDBC#xff1f;2.2 JDBC 核心思想2.2.1 MySQL 数据库驱动2.2.2 JDBC API 2.3 环境搭建 三、JD… 文章目录 一、引言1.1 如何操作数据库1.2 实际开发中会采用客户端操作数据库吗 二、JDBCJava Database Connectivity2.1 什么是 JDBC2.2 JDBC 核心思想2.2.1 MySQL 数据库驱动2.2.2 JDBC API 2.3 环境搭建 三、JDBC 开发步骤【重点】3.1 注册驱动3.2 连接数据库3.3 获取发送 SQL 的对象3.4 执行SQL 语句3.5 处理结果3.6 释放资源3.7 综合案例 四、ResultSet结果集4.1 接收结果集4.2 遍历 ResultSet 中的数据4.2.1 遍历方法 4.3 综合案例4.3.1 根据列的名称获取4.3.2 根据列的编号获取数据 五、 常见错误六、 综合案例【登录】6.1 创建表6.2 实现登录 七、SQL注入问题7.1 什么是 SQL 注入7.2 如何避免 SQL 注入 八、PreparedStatement【重点】8.1 PreparedStatement的应用8.1.1 参数标记8.1.2 动态参数绑定 九、封装工具类9.1 重用性方案9.1.1 重用工具类实现 9.2 跨平台方案9.2.1 跨平台工具类实现 十、ORM10.1 实体类(entity)零散数据的载体10.1.1 ORM应用 十一、 DAO 数据访问对象Data Access Object11.1 创建数据库11.2 封装实体类11.3 编写 DaoImpl 类 十二、Date工具类12.1 java.util.Date12.2 java.sql.Date12.3 SimpleDateFormat12.3.1 SimpleDateFormat应用 12.4 封装DateUtils工具类 十三、Service业务逻辑层13.1 什么是业务13.2 Service开发流程13.2.1 编写 service 实现转账功能 十四、事务14.1 service 层控制事务14.2 解决方案1传递 Connection14.2.1 传递的问题 14.3 解决方案2ThreadLocal14.4 ThreadLocal应用14.4.1 参数绑定 十五、 事务的封装15.1 完善工具类 十六、 三层架构16.1 什么是三层16.2 三层架构项目搭建按开发步骤 十七、DaoUtils17.1 commonsUpdate17.2 commonsSelect 十八、Druid连接池18.1 Druid 连接池使用步骤18.1.1 database.properties配置文件18.1.2 连接池工具类 十九、Apache的DbUtils使用19.1 DbUtils简介19.1.1 DbUtils主要包含 19.2 DbUtils的使用步骤19.2.1 DbUtils工具类19.2.2 UserDaoImpl 数据访问对象11.1.2 模拟转账错误 11.2 事务的概念11.3 事务的边界11.4 事务的原理11.5 事务的特性ACID11.6 事务应用11.6.1 事务完成转账 一、引言 1.1 如何操作数据库 使用客户端工具访问数据库需要手工建立连接输入用户名和密码登录编写 SQL 语句点击执行查看操作结果结果集或受影响行数。 客户端操作数据库步骤 1.2 实际开发中会采用客户端操作数据库吗 在实际开发中当用户的数据发生改变时不可能通过客户端操作执行 SQL 语句因为操作量过大无法保证效率和正确性。 二、JDBCJava Database Connectivity 2.1 什么是 JDBC JDBCJava Database Connectivity Java 连接数据库的规范标准可以使用 Java 语言连接数据库完成 CRUD 操作。 2.2 JDBC 核心思想 Java 中定义了访问数据库的接口可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类Driver 数据库驱动。 核心思想 2.2.1 MySQL 数据库驱动 mysql-connector-java-5.1.X 适用于 5.X 版本mysql-connector-java-8.0.X 适用于 8.X版本 2.2.2 JDBC API JDBC 是由多个接口和类进行功能实现。 类型权限定名简介classjava.sql.DriverManager管理多个数据库驱动类提供了获取数据库连接的方法interfacejava.sql.Connection代表一个数据库连接当connection不是null时表示已连接数据库interfacejava.sql.Statement发送SQL语句到数据库工具interfacejava.sql.ResultSet保存SQL查询语句的结果数据结果集classjava.sql.SQLException处理数据库应用程序时所发生的异常 2.3 环境搭建 在项目下新建 lib 文件夹用于存放 jar 文件。将 mysql 驱动mysql-connector-java-5.1.X复制到项目的 lib 文件夹中。选中 lib 文件夹右键 Add as Libraay点击 OK。 三、JDBC 开发步骤【重点】 3.1 注册驱动 使用 Class.forName(“com.mysql.jdbc.Driver”);手动加载字节码文件到 JVM 中。 Class.forName(com.mysql.jdbc.Driver);//加载驱动3.2 连接数据库 通过 DriverManager.getConnection(url,user,password) 获取数据库连接对象 URL:jdbc:mysql://localhost:3306/databaseusername:rootpassword:1234 Connection conn DriverManager.getConnection(jdbc:mysql://localhost:3306/database?useUnicodetruecharacterEncodingutf8, root,1234);URL(Uniform Resource Locator) 统一资源定位符由协议、IP、端口、SID程序实例名称组成 3.3 获取发送 SQL 的对象 通过 Connection 对象获得 Statement 对象用于对数据库进行通用访问。 Statement statement conn.createStatement();3.4 执行SQL 语句 执行 SQL 语句并接收执行结果。 String sql INSERT INTO t_jobs(JOB_ID,JOB_TITLE,MIN_SALARY,MAX_SALARY) VALUES(JAVA_Le,JAVA_Lecturer,4000,10000);;int result statement.executeUpdate(sql);//执行SQL语句并接收结果注意在编写 DML 语句时一定要注意字符串参数的符号是单引号 ‘值’DML 语句增删改时返回受影响行数int 类型。DQL 语句查询时返回结果数据(ResultSet 结果集)。 3.5 处理结果 接受处理操作结果。 if(result 1){System.out.println(Success); }受影响行数逻辑判断、方法返回。查询结果集迭代、依次获取。 3.6 释放资源 遵循先开后关原则释放所使用到的资源对象。 statement.close(); conn.close();3.7 综合案例 整合以上核心六步实现向数据库表中插入一条数据。 package com.qf.JDBC;import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement;public class DeleteJdbc {public static void main(String[] args) throws Exception{//1.加载驱动Class.forName(com.mysql.jdbc.Driver);//2.获得连接对象Connection connection DriverManager.getConnection(jdbc:mysql://localhost:3306/companydb,root,1234);//3.获得执行SQL的对象Statement statement connection.createStatement();//4.执行SQL语句并接收结果int result statement.executeUpdate(delete from t_jobs where job_id H5_mgr;);//5.处理结果if(result1){System.out.println(删除成功);}else{System.out.println(删除失败);}//6.释放资源statement.close();connection.close();} } 四、ResultSet结果集 在执行查询 SQL 后存放查询到的结果集数据。 4.1 接收结果集 ResultSet rs statement.executeQuery(sql); ResultSet rs statement.executeQuery(SELECT * FROM t_employees;);4.2 遍历 ResultSet 中的数据 ResultSet 以表table结构进行临时结果的存储需要通过 JDBC API 将其中数据进行依次获取。 数据行指针初始位置在第一行数据前每调用一次 boolean next()方法ResultSet 的指针向下移动一行结果为 true表示当前行有数据。rs.getXxx(整数);代表根据列的编号顺序获得从 1 开始。rs.getXxx(“列名”);代表根据列名获得。 boolean next() throws SQLException //判断 rs 结果集中下一行是否存在数据4.2.1 遍历方法 int getInt(int columnIndex) throws SQLException //获得当前行第N列的int值 int getInt(String columnLabel) throws SQLException //获得当前行columnLabel列的int值double getDouble(int columnIndex) throws SQLException //获得当前行第N列的double值 double getDouble(String columnLabel) throws SQLException //获得当前行columnLabel列的double值String getString(int columnIndex) throws SQLException //获得当前行第N列的String值 String getString(String columnLabel) throws SQLException //获得当前行columnLabel列的String值......注意列的编号从 1 开始。 4.3 综合案例 对 t_jobs 表中的所有数据进行遍历。 4.3.1 根据列的名称获取 package com.qf.www.test;import java.sql.*;public class JobsQuery {public static void main(String[] args) {//1.加载驱动Class.forName(com.mysql.jdbc.Driver);//2.获取数据库连接对象Connection connection DriverManager.getConnection(jdbc:mysql://localhost:3306/product, root, 1234);//3.获取发送 sql 语句对象Statement statement connection.createStatement();//4.执行 SQL 语句并接收结果集ResultSet resultSet statement.executeQuery(select * from t_jobs);//5 处理结果集while(resultSet.next()){//5.1有数据依据列名获取数据String job_id resultSet.getString(job_id);String job_title resultSet.getString(job_title);int min_salary resultSet.getInt(min_salary);int max_salary resultSet.getInt(max_salary);System.out.println(job_id\tjob_title\tmin_salary\tmax_salary);}//6.释放资源rs.close();statement.close();connection.close();}}} } 4.3.2 根据列的编号获取数据 //。。。。与上无异while(resultSet.next()){//5.2有数据依据列名获取数据String job_id resultSet.getString(1);String job_title resultSet.getString(2);int min_salary resultSet.getInt(3);int max_salary resultSet.getInt(4);System.out.println(job_id\tjob_title\tmin_salary\tmax_salary);}//释放资源五、 常见错误 java.lang.ClassNotFoundException找不到类类名书写错误、没有导入jar包java.sql.SQLException与sql语句相关的错误 约束错误、表名列名书写错误 建议在客户端工具中测试SQL语句之后再粘贴在代码中com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 原因列值Sting类型没有加单引号Duplicate entry ‘1’ for key ‘PRIMARY’ 原因主键值已存在或混乱更改主键值或清空表com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column ‘password’ in 原因可能输入的值的类型不对确定是否插入的元素时对应的值的类型正确 六、 综合案例【登录】 6.1 创建表 创建一张用户表 User id 主键、自动增长。用户名字符串类型唯一、非空密码字符串类型非空手机号码字符串类型 插入 2 条测试语句 6.2 实现登录 通过控制台用户输入用户名和密码。用户输入的用户名和密码作为条件编写查询 SQL 语句。如果该用户存在提示登录成功反之提示失败。 七、SQL注入问题 7.1 什么是 SQL 注入 用户输入的数据中有 SQL 关键字或语法并且参与了 SQL 语句的编译导致 SQL 语句编译后的条件含义为 true一直得到正确的结果。这种现象称为 SQL 注入。 7.2 如何避免 SQL 注入 由于编写的 SQL 语句是在用户输入数据整合后再进行编译。所以为了避免 SQL 注入的问题我们要使 SQL 语句在用户输入数据前就已进行编译成完整的 SQL 语句再进行填充数据。 八、PreparedStatement【重点】 PreparedStatement 继承了 Statement 接口执行 SQL 语句的方法无异。 8.1 PreparedStatement的应用 作用 预编译SQL 语句效率高。 安全避免SQL注入 。 可以动态的填充数据执行多个同构的 SQL 语句。 8.1.1 参数标记 //1.预编译 SQL 语句 PreparedStatement pstmt conn.prepareStatement(select * from user where username? and password?);注意JDBC中的所有参数都由 符号占位这被称为参数标记。在执行SQL语句之前必须为每个参数提供值。 8.1.2 动态参数绑定 pstmt.setXxx(下标,值) 参数下标从 1 开始为指定参数下标绑定值 //1.预编译 SQL 语句 PreparedStatement pstmt conn.prepareStatement(select * from user where username? and password?); //2.为参数下标赋值 pstmt.setString(1,username); pstmt.setString(2,password);九、封装工具类 在实际JDBC的使用中存在着大量的重复代码:例如连接数据库、关闭数据库等这些操作我们需要把传统的JDBC代码进行重构抽取出通用的JDBC工具类以后连接任何数据库、释放资源都可以使用这个工具类。 工具类核心思想 9.1 重用性方案 封装获取连接、释放资源两个方法。 提供public static Connection getConnection(){}方法。提供public static void closeAll(Connection conn , Statement sm , ResultSet rs){}方法。 9.1.1 重用工具类实现 package com.qf.JDBC;import java.sql.*;/*** 重用性方案* 获取连接* 释放资源*/ public class DBUtils {static {//类加载执行一次try {Class.forName(com.mysql.jdbc.Driver);} catch (ClassNotFoundException e) {e.printStackTrace();}}//1.获取连接public static Connection getConnection() {Connection connection null;try {connection DriverManager.getConnection(jdbc:mysql://localhost:3306/companydb, root, 1234);} catch (SQLException e) {e.printStackTrace();}return connection;}//2.释放资源public static void closeAll(Connection connection, Statement statement, ResultSet resultSet) {try {if (resultSet ! null) {resultSet.close();}if (statement ! null) {statement.close();}if (connection ! null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}} } 9.2 跨平台方案 定义public static final Properties prop new Properties(); //读取配置文件的Map 定义static{ //首次使用工具类时加载驱动 InputStream is JDBCUtil.class.getResourceAsStream(“路径”); //通过复用本类自带流读取jdbc.properties配置文件。classPath bin prop.load(is); //通过prop对象将流中的配置信息分割成键值对 String driverName prop.getProperty(“driver”); //通过driverName的键获取对应的值com.mysql.jdbc.Driver Class.forName(driverName); //加载驱动 } 9.2.1 跨平台工具类实现 在src 目录下新建 db.properties 文件。 drivercom.mysql.jdbc.Driver urljdbc:mysql://localhost:3306/mydb3 userroot password1234工具类的封装。 package com.qf.jdbc2;import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties;public class DBUtils {private static final Properties PROPERTIES new Properties();//存储配置文件的mapstatic {InputStream is DBUtils.class.getResourceAsStream(/db.properties);try {PROPERTIES.load(is);//通过流将配置文件内容加载到properties集合Class.forName(PROPERTIES.getProperty(driver));} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}}public static Connection getConnection() {Connection connection null;try {connection DriverManager.getConnection(PROPERTIES.getProperty(url), PROPERTIES.getProperty(username), PROPERTIES.getProperty(password));} catch (SQLException e) {e.printStackTrace();}return connection;}public static void closeAll(Connection connection, Statement statement, ResultSet resultSet) {try {if (resultSet ! null) {resultSet.close();}if (statement ! null) {statement.close();}if (connection ! null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}} } JSON jacksongsonfastjson 十、ORM ORMObject Relational Mapping。 从数据库查询到的结果集(ResultSet)在进行遍历时逐行遍历取出的都是零散的数据。在实际应用开发中我们需要将零散的数据进行封装整理。 10.1 实体类(entity)零散数据的载体 一行数据中多个零散的数据进行整理。通过entity的规则对表中的数据进行对象的封装。表名类名列名属性名提供各个属性的get、set方法。提供无参构造方法、(视情况添加有参构造)。 10.1.1 ORM应用 entity实体类 package com.qf.www.test;public class T_Jobs {private String job_id;private String job_title;private int min_salary;private int max_salary;Overridepublic String toString() {return T_Jobs{ job_id job_id \ , job_title job_title \ , min_salary min_salary , max_salary max_salary };}public String getJob_id() {return job_id;}public void setJob_id(String job_id) {this.job_id job_id;}public String getJob_title() {return job_title;}public void setJob_title(String job_title) {this.job_title job_title;}public int getMin_salary() {return min_salary;}public void setMin_salary(int min_salary) {this.min_salary min_salary;}public int getMax_salary() {return max_salary;}public void setMax_salary(int max_salary) {this.max_salary max_salary;}public T_Jobs() {}public T_Jobs(String job_id, String job_title, int min_salary, int max_salary) {this.job_id job_id;this.job_title job_title;this.min_salary min_salary;this.max_salary max_salary;} } 查询结果封装 package com.qf.www.test;import java.sql.*;public class JobsQuery {public static void main(String[] args) {Connection connection null;Statement statement null;ResultSet resultSet null;String URL jdbc:mysql://localhost:3306/product;String user root;String password 1234;try {//1.加载驱动Class.forName(com.mysql.jdbc.Driver);//2.获取数据库连接对象connection DriverManager.getConnection(URL, user, password);//3.编写 SQL 语句String sql select * from t_jobs;//4.获取发送 sql 语句对象statement connection.createStatement();//5.执行 SQL 语句并接收结果集resultSet statement.executeQuery(sql);//5.1使用 while 循环判断下一行是否有数据while(resultSet.next()){//5.2有数据依据列名获取数据String job_id resultSet.getString(1);String job_title resultSet.getString(2);int min_salary resultSet.getInt(3);int max_salary resultSet.getInt(4);//5.3 创建实体类对象T_Jobs t_jobs new T_Jobs();//5.4 每列数据对应属性进行赋值t_jobs.setJob_id(job_id);t_jobs.setJob_title(job_title);t_jobs.setMin_salary(min_salary);t_jobs.setMax_salary(max_salary);System.out.println(t_jobs);}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {//6.释放资源if (resultSet ! null) {resultSet.close();}if (statement ! null) {statement.close();}if (connection ! null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}} } 十一、 DAO 数据访问对象Data Access Object DAO 实现了业务逻辑与数据库访问相分离。 对同一张表的所有操作封装在XxxDaoImpl对象中。根据增删改查的不同功能实现具体的方法insert、update、delete、select、selectAll。 DAO流程 11.1 创建数据库 创建一张表 Person有以下列 idint主键自动增长namevarchar(20) 非空ageint 非空bornDateDateemail字符串address字符串 11.2 封装实体类 创建entity实体类 Person编写属性私有化构造方法get/set 方法。 11.3 编写 DaoImpl 类 编写 DaoImpl 类提供增删改查方法使用 JDBC 开发步骤完成功能。 package com.qf.person;import sun.awt.image.DataBufferNative;import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List;/*** 增、删、改、查单个、查所有* 只做数据库访问操作不参与逻辑判断* 数据库一张表的访问的操作复用*/ public class PersonDaoImpl {//新增public int insert(Person person){Connection connection null;PreparedStatement preparedStatement null;String sql insert into person(name,age,borndate,email,address) values(?,?,?,?,?);;try {connection DBUtils.getConnection();preparedStatement connection.prepareStatement(sql);preparedStatement.setString(1,person.getName());preparedStatement.setInt(2,person.getAge());preparedStatement.setDate(3,null);preparedStatement.setString(4,person.getEmail());preparedStatement.setString(5,person.getAddress());int result preparedStatement.executeUpdate();return result;} catch (SQLException e) {e.printStackTrace();}finally {DBUtils.closeAll(connection,preparedStatement,null);}return 0;}//修改public int update(Person person){Connection connection null;PreparedStatement preparedStatement null;String sql update person set name?,age?,borndate?,email?,address? where id ?;try {connection DBUtils.getConnection();preparedStatement connection.prepareStatement(sql);preparedStatement.setString(1,person.getName());preparedStatement.setInt(2,person.getAge());preparedStatement.setDate(3,null);preparedStatement.setString(4,person.getEmail());preparedStatement.setString(5,person.getAddress());preparedStatement.setInt(6,person.getId());int result preparedStatement.executeUpdate();return result;} catch (SQLException e) {e.printStackTrace();}finally {DBUtils.closeAll(connection,preparedStatement,null);}return 0;}//删除public int delete(int id){Connection connection null;PreparedStatement preparedStatement null;String sql delete from person where id ?;;connection DBUtils.getConnection();try {preparedStatement connection.prepareStatement(sql);preparedStatement.setInt(1,id);int result preparedStatement.executeUpdate();return result;} catch (SQLException e) {e.printStackTrace();}finally {DBUtils.closeAll(connection,preparedStatement,null);}return 0;}//查单个public Person select(int id){Connection connection null;PreparedStatement preparedStatement null;ResultSet resultSet null;String sql select * from person where id ?;;Person person null;try {connection DBUtils.getConnection();preparedStatement connection.prepareStatement(sql);preparedStatement.setInt(1,id);resultSet preparedStatement.executeQuery();if(resultSet.next()){person new Person();int pid resultSet.getInt(id);String name resultSet.getString(name);int age resultSet.getInt(age);Date bornDate resultSet.getDate(borndate);String email resultSet.getString(email);String address resultSet.getString(address);person.setId(pid);person.setName(name);person.setAge(age);person.setBornDate(bornDate);person.setEmail(email);person.setAddress(address);}return person;} catch (SQLException e) {e.printStackTrace();}finally {DBUtils.closeAll(connection,preparedStatement,resultSet);}return null;}//查所有public ListPerson selectAll(){Connection connection null;PreparedStatement preparedStatement null;ResultSet resultSet null;Person person null;ListPerson personList new ArrayList();try {connection DBUtils.getConnection();preparedStatement connection.prepareStatement(select * from person;);resultSet preparedStatement.executeQuery();while(resultSet.next()){int pid resultSet.getInt(id);String name resultSet.getString(name);int age resultSet.getInt(age);Date bornDate resultSet.getDate(borndate);String email resultSet.getString(email);String address resultSet.getString(address);person new Person(pid,name,age,bornDate,email,address);personList.add(person);}return personList;} catch (Exception e) {e.printStackTrace();}return null;} }十二、Date工具类 现有问题数据库存储的数据类型为java.sql.Date。而我们Java应用层存储日期类型为java.util.Date。当我们用Java应用程序插入带有日期的数据到数据库中时需要进行转换。 12.1 java.util.Date Java语言常规应用层面的日期类型可以通过字符串创建对应的时间对象。无法直接通过JDBC插入到数据库。 12.2 java.sql.Date 不可以通过字符串创建对应的时间对象只能通过毫秒值创建对象(1970年至今的毫秒值)。可以直接通过JDBC插入到数据库。 12.3 SimpleDateFormat 格式化和解析日期的具体类。允许进行格式化日期 - 文本、解析文本 - 日期和规范化。 12.3.1 SimpleDateFormat应用 SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd);//指定日期格式java.util.Date date sdf.parse(String dateStr);//将字符串解析成日期类型java.util.DateString dates sdf.format(date);//将日期格式化成字符串12.4 封装DateUtils工具类 package com.qf.day43.t4;import java.text.ParseException; import java.text.SimpleDateFormat;/*** 日期转换* 字符串转UtilDate* UtilDate转SqlDate* utilDate转成字符串*/ public class DateUtils {private static final SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyy-MM-dd);//字符串转Utilpublic static java.util.Date strToUtilDate(String str) {try {return simpleDateFormat.parse(str);} catch (ParseException e) {e.printStackTrace();}return null;}//util转sqlpublic static java.sql.Date utilToSql(java.util.Date date){return new java.sql.Date(date.getTime());}//util转字符串public static String toStr(java.util.Date bornDate){return sdf.format(bornDate);} }十三、Service业务逻辑层 13.1 什么是业务 代表用户完成的一个业务功能可以由一个或多个DAO的调用组成。软件所提供的一个功能都叫业务。 service 层核心思想 13.2 Service开发流程 service 开发流程 13.2.1 编写 service 实现转账功能 package com.qf.day44.accounts;import java.sql.Connection; import java.sql.SQLException;public class T_AccountServiceImpl {/*** 转账业务** param fromNo 转账卡号* param pwd 转账卡号密码* param toNo 收钱卡号* param money 转账金额*/public String transfer(String fromNo, String pwd, String toNo, double money) {//收参String result 转账失败;//2.组织业务功能T_AccountDaoImpl accountDao new T_AccountDaoImpl();try {//2.1验证fromNo是否存在T_Account fromAcc accountDao.select(fromNo);if (fromAcc null) {throw new RuntimeException(----卡号不存在-----);}//2.2验证fromNo的密码是否正确if (!fromAcc.getPassword().equals(pwd)) {throw new RuntimeException(----密码错误----);}//2.3验证余额是否充足if (fromAcc.getBalance() money) {throw new RuntimeException(----余额不足----);}//2.4验证toNo是否存在T_Account toAcc accountDao.select(toNo);if (toAcc null) {throw new RuntimeException(----对方卡号不存在----);}//2.5减少fromNo的余额//修改自己的金额将余额-转账金额替换原有的属性fromAcc.setBalance(fromAcc.getBalance() - money);accountDao.update(fromAcc);//2.6增加toNo的余额toAcc.setBalance(toAcc.getBalance() money);accountDao.update(toAcc);result 转账成功;} catch (Exception e) {e.printStackTrace();}finally {DBUtils.closeAll(connection,null,null);}return result;} } 十四、事务 在JDBC 中获得 Connection 对象开始事务–提交或回滚–关闭连接。其事务策略是 conn.setAutoCommit(false);//true 等价于 1false 等价于 0conn.commit();//手动提交事务conn.rollback();//手动回滚事务 14.1 service 层控制事务 package com.qf.day44.accounts;import java.sql.Connection; import java.sql.SQLException;public class T_AccountServiceImpl {/*** 转账业务** param fromNo 转账卡号* param pwd 转账卡号密码* param toNo 收钱卡号* param money 转账金额*/public String transfer(String fromNo, String pwd, String toNo, double money) {//收参String result 转账失败;//2.组织业务功能T_AccountDaoImpl accountDao new T_AccountDaoImpl();//拿一个连接Connection connection null;try {//建立了一个数据库连接connection DBUtils.getConnection();//开启事务 并且关闭事务的自动提交connection.setAutoCommit(false);//2.1验证fromNo是否存在T_Account fromAcc accountDao.select(fromNo);if (fromAcc null) {throw new RuntimeException(----卡号不存在-----);}//2.2验证fromNo的密码是否正确if (!fromAcc.getPassword().equals(pwd)) {throw new RuntimeException(----密码错误----);}//2.3验证余额是否充足if (fromAcc.getBalance() money) {throw new RuntimeException(----余额不足----);}//2.4验证toNo是否存在T_Account toAcc accountDao.select(toNo);if (toAcc null) {throw new RuntimeException(----对方卡号不存在----);}//2.5减少fromNo的余额//修改自己的金额将余额-转账金额替换原有的属性fromAcc.setBalance(fromAcc.getBalance() - money);accountDao.update(fromAcc);int a 10/0;//模拟程序转账出现异常//2.6增加toNo的余额toAcc.setBalance(toAcc.getBalance() money);accountDao.update(toAcc);result 转账成功;//执行到这里没有异常则提交事务connection.commit();} catch (Exception e) {e.printStackTrace();try {//出现异常回滚System.out.println(出现了异常回滚整个事务);connection.rollback();} catch (SQLException ex) {ex.printStackTrace();}}finally {DBUtils.closeAll(connection,null,null);}return result;} } 问题当转账程序出现异常事务控制成功了吗 14.2 解决方案1传递 Connection 为了解决线程中Connection 对象不同步的问题可以将 Connection对象通过 service传递给各个DAO 方法吗 14.2.1 传递的问题 如果使用传递Connection容易造成接口污染BadSmell。定义接口是为了更容易更换实现而将 Connection定义在接口中会造成污染当前接口。 14.3 解决方案2ThreadLocal 可以将整个线程中单线程中存储一个共享值。线程拥有一个类似 Map 的属性键值对结构ThreadLocal对象值。 14.4 ThreadLocal应用 一个线程共享同一个 ThreadLocal在整个流程中任一环节可以存值或取值。 ThreadLocal核心流程 14.4.1 参数绑定 在 DBUtils中将当前 Connection对象添加到 ThreadLocal 中。 ThreadLocalConnection tl new ThreadLocalConnection();//getConnection 方法修改 public static Connection getConnection(){Connection conn tl.get();//获取线程中存储的 Connection 对象if(conn null){conn ds.getConnection();//从连接池中获取一个连接tl.set(conn);//存储到线程对象中。}return conn; }//关闭所有连接 增加 tl.remove(); 移除public static void closeAll(ResultSet rs, Statement st, Connection conn) {try {if (rs ! null) {rs.close();}if (st ! null) {st.close();}if (conn ! null) {conn.close();tl.remove();//将 conn 移除。}} catch (SQLException e) {e.printStackTrace();}} 十五、 事务的封装 将事务的开启、提交、回滚都封装在工具类中业务层调用即可。 15.1 完善工具类 //开启事务public static void begin(){Connection connection getConnection();try {connection.setAutoCommit(false);} catch (SQLException e) {e.printStackTrace();}}//提交事务public static void commit(){Connection connection getConnection();try {connection.commit();} catch (SQLException e) {e.printStackTrace();}finally {DBUtils.closeAll(connection,null,null);}}//回滚事务public static void rollback(){Connection connection getConnection();try {connection.rollback();} catch (SQLException e) {e.printStackTrace();}finally {DBUtils.closeAll(connection,null,null);}}十六、 三层架构 16.1 什么是三层 表示层 命名XXXView职责收集用户的数据和需求、展示数据。 业务逻辑层 命名XXXServiceImpl职责数据加工处理、调用DAO完成业务实现、控制事务。 数据访问层 命名XXXDaoImpl职责向业务层提供数据将业务层加工后的数据同步到数据库。 三层架构核心流程 16.2 三层架构项目搭建按开发步骤 utils 存放工具类DBUtilsentity 存放实体类Persondao 存放 DAO 接口PersonDao impl 存放 DAO 接口实现类PersonDaoImpl service 存放 service 接口PersonService impl 存放 service 接口实现类PersonServiceImpl view 存放程序启动类main 程序设计时考虑易修改、易扩展为Service层和DAO层设计接口便于未来更换实现类 十七、DaoUtils 在DAO层中对数据库表的增、删、改、查操作存在代码冗余可对其进行抽取封装DaoUtils工具类实现复用。 17.1 commonsUpdate /*** 公共处理增、删、改的方法* sql语句参数列表** param sql 执行的sql语句* param args 参数列表。为占位符赋值* return*/public int commonsUpdate(String sql, Object... args) {Connection connection null;PreparedStatement preparedStatement null;try {connection DBUtils.getConnection();preparedStatement connection.prepareStatement(sql);for (int i 0; i args.length; i) {preparedStatement.setObject(i 1, args[i]);}return preparedStatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();} finally {DBUtils.closeAll(null, preparedStatement, null);}return 0;} 17.2 commonsSelect /*** 公共查询方法 (可查询单个对象也可查询多个对象,可以查任何一张表)** param sql* param args* return*/// select * from t_account// select * from t_student//工具不知道查的是什么 调用者知道//封装对象、对象赋值 调用者清楚public ListT commonsSelect(String sql, RowMapperT rowMapper, Object... args) {ListT elements new ArrayListT();Connection connection null;PreparedStatement preparedStatement null;ResultSet resultSet null;try {connection DBUtils.getConnection();preparedStatement connection.prepareStatement(sql);if(args !null){for (int i 0; i args.length; i) {preparedStatement.setObject(i 1, args[i]);}}resultSet preparedStatement.executeQuery();while (resultSet.next()) {//根据查询到的结果完成ORM如何进行对象的创建及赋值T t rowMapper.getRow(resultSet);//回调----调用者提供的一个封装方法ORMelements.add(t);}} catch (SQLException e) {e.printStackTrace();} finally {DBUtils.closeAll(null, preparedStatement, resultSet);}return elements;}十八、Druid连接池 DBCP、C3P0 ThreadLocal WebFlux 在程序初始化时预先创建指定数量的数据库连接对象存储在池中。当需要连接数据库时从连接池中取出现有连接使用完毕后也不会进行关闭而是放回池中实现复用节省资源。 18.1 Druid 连接池使用步骤 创建 database.properties 配置文件。引入druid-1.1.5.jar 文件。 18.1.1 database.properties配置文件 #连接设置 driverClassNamecom.mysql.jdbc.Driver urljdbc:mysql://localhost:3306/school usernameroot passwordroot #!-- 初始化连接 -- initialSize10 #最大连接数量 maxActive50 #!-- 最小空闲连接 -- minIdle5 #!-- 超时等待时间以毫秒为单位 60000毫秒/1000等于60秒 -- maxWait500018.1.2 连接池工具类 public class DbUtils {//声明连接池对象private static DruidDataSource ds;static{//实例化配置对象Properties propertiesnew Properties();try {//加载配置文件内容properties.load(DbUtils.class.getResourceAsStream(database.properties));ds (DruidDataSource)DruidDataSourceFactory.createDataSource(properties); } catch (IOException e) {e.printStackTrace();}}//获取连接对象public static Connection getConnection() {try {return ds.getConnection();} catch (SQLException e) {e.printStackTrace();}return null;}//释放资源。。 }十九、Apache的DbUtils使用 Commons DbUtils 是Apache组织提供的一个对JDBC进行简单封装的开源工具类库使用它能勾简化JDBC应用程序的开发同时不会影响程序的性能。 19.1 DbUtils简介 DbUtils是Java编程中数据库操作实用小工具小巧、简单、实用 对于数据表的查询操作可以把结果转换为List、Array、Set等集合。便于操作。对于数据表的DML操作也变得很简单(只需要写SQL语句)。 19.1.1 DbUtils主要包含 ResultSetHandler接口转换类型接口 BeanHandler类实现类把一条记录转换成对象BeanListHandler类实现类把多条记录转换成List集合。ScalarHandler类实现类适合获取一行一列的数据。 QueryRunner执行sql语句的类 增、删、改update();查询query(); 19.2 DbUtils的使用步骤 导入jar包 mysql连接驱动jar包druid-1.1.5.jardatabase.properties配置文件commons-dbutils-1.6.jar 19.2.1 DbUtils工具类 package com.project.utils;import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.util.Properties;/*** 连接池工具类*/ public class DBUtils {private static DruidDataSource dataSource;static {Properties properties new Properties();InputStream is DBUtils.class.getResourceAsStream(/database.properties);try {properties.load(is);dataSource (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}// 返回一个数据源public static DataSource getDataSource(){return dataSource;} } 19.2.2 UserDaoImpl 数据访问对象 package com.project.dao.impl;import com.project.dao.UserDao; import com.project.entity.User; import com.project.utils.DBUtils; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler;import java.sql.SQLException; import java.util.List;public class UserDaoImpl implements UserDao {//1.创建QueryRunner对象并传递一个数据源对象private QueryRunner queryRunner new QueryRunner(DBUtils.getDataSource());Overridepublic int insert(User user) {Object[] params{user.getId(),user.getUsername(),user.getPassword(),user.getSex(),user.getEmail(),user.getAddress()};try {return queryRunner.update(insert into user (id,username,password,sex,email,address) values(?,?,?,?,?,?),params);} catch (SQLException e) {e.printStackTrace();}return 0;}Overridepublic int update(User user) {Object[] params{user.getUsername(),user.getPassword(),user.getSex(),user.getEmail(),user.getAddress(),user.getId()};try {return queryRunner.update(update user set username?,password?,sex?,email?,address? where id ?,params);} catch (SQLException e) {e.printStackTrace();}return 0;}Overridepublic int delete(int id) {try {return queryRunner.update(delete from user where id ?,id);} catch (SQLException e) {e.printStackTrace();}return 0;}Overridepublic User select(int id) {try {//把查询到的记录封装成 指定对象return queryRunner.query(select * from user where id ?, new BeanHandlerUser(User.class), id);} catch (SQLException e) {e.printStackTrace();}return null;}/*** 查询所有* return*/Overridepublic ListUser selectAll() {try {return queryRunner.query(select * from user;,new BeanListHandlerUser(User.class));} catch (SQLException e) {e.printStackTrace();}return null;} } ### 十一、事务【重点】------#### 11.1 模拟转账 生活当中转账是转账方账户扣钱收账方账户加钱。我们用数据库操作来模拟现实转账。##### 11.1.1 数据库模拟转账mysql #A 账户转账给 B 账户 1000 元。 #A 账户减1000 元 UPDATE account SET MONEY MONEY-1000 WHERE id1;#B 账户加 1000 元 UPDATE account SET MONEY MONEY1000 WHERE id2;上述代码完成了两个账户之间转账的操作。 11.1.2 模拟转账错误 #A 账户转账给 B 账户 1000 元。 #A 账户减1000 元 UPDATE account SET MONEY MONEY-1000 WHERE id1; #断电、异常、出错...#B 账户加 1000 元 UPDATE account SET MONEY MONEY1000 WHERE id2;上述代码在减操作后过程中出现了异常或加钱语句出错会发现减钱仍旧是成功的而加钱失败了注意每条 SQL 语句都是一个独立的操作一个操作执行完对数据库是永久性的影响。 11.2 事务的概念 事务是一个原子操作。是一个最小执行单元。可以由一个或多个SQL语句组成在同一个事务当中所有的SQL语句都成功执行时整个事务成功有一个SQL语句执行失败整个事务都执行失败。 11.3 事务的边界 开始连接到数据库执行一条DML语句。 上一个事务结束后又输入了一条DML语句即事务的开始 结束 ​ 1). 提交 ​ a. 显示提交commit; ​ b. 隐式提交一条创建、删除的语句正常退出客户端退出连接; ​ 2). 回滚 ​ a. 显示回滚rollback; ​ b. 隐式回滚非正常退出断电、宕机执行了创建、删除的语句但是失败了会为这个无效的语句执行回滚。 11.4 事务的原理 数据库会为每一个客户端都维护一个空间独立的缓存区(回滚段)一个事务中所有的增删改语句的执行结果都会缓存在回滚段中只有当事务中所有SQL 语句均正常结束commit才会将回滚段中的数据同步到数据库。否则无论因为哪种原因失败整个事务将回滚rollback。 11.5 事务的特性ACID Atomicity(原子性) 表示一个事务内的所有操作是一个整体要么全部成功要么全部失败 Consistency(一致性) 表示一个事务内有一个操作失败时所有的更改过的数据都必须回滚到修改前状态 Isolation(隔离性) 事务查看数据操作时数据所处的状态要么是另一并发事务修改它之前的状态要么是另一事务修改它之后的状态事务不会查看中间状态的数据。 Durability(持久性) 持久性事务完成之后它对于系统的影响是永久性的。 11.6 事务应用 应用环境基于增删改语句的操作结果均返回操作后受影响的行数可通过程序逻辑手动控制事务提交或回滚 11.6.1 事务完成转账 #A 账户给 B 账户转账。 #1.开启事务 START TRANSACTION;|setAutoCommit0;#禁止自动提交 setAutoCommit1;#开启自动提交 #2.事务内数据操作语句 UPDATE ACCOUNT SET MONEY MONEY-1000 WHERE ID 1; UPDATE ACCOUNT SET MONEY MONEY1000 WHERE ID 2; #3.事务内语句都成功了执行 COMMIT COMMIT; #4.事务内如果出现错误执行 ROLLBACK; ROLLBACK;注意开启事务后执行的语句均属于当前事务成功再执行 COMIIT失败要进行 ROLLBACK
http://www.pierceye.com/news/896470/

相关文章:

  • 门户网站建设自查报告网站关键词快速排名技术
  • 如何建网站费用多少全国工商企业查询平台
  • 兰州新区建站什么是网络营销取得成功的基础
  • 南昌 网站 公司wordpress迁移后媒体库丢失
  • 做移动网站点击软件cnzz网站建设
  • 高质量网站外链建设大揭秘做网站之前需要准备什么条件
  • 睢宁做网站百度一下做网站
  • 做国外购物网站国家高职示范校建设网站
  • 网站建设福州公司山西省大同市网站建设公司
  • 浙江网站建设推荐wordpress 增加小工具
  • 个人网站是商业的吗北京网站建设设计
  • 手机网站收费怎么停止网站
  • 网站建设 金疙瘩计划杭州小程序制作公司排行榜
  • 德泰诺网站建设软件著作权登记证书
  • 商标设计网页seo外包公司兴田德润官方地址
  • 网站开发人员岗位成功营销案例分享
  • 赤峰做网站的公司湘潭哪里做网站
  • 免费自助建站郑州官网seo费用
  • 称心的常州网站建设wordpress怎么用两个主题
  • 建设银行北京分行网站做视频网站用什么服务器配置
  • 网站备案流程实名认证医疗网站建设资讯
  • 一个做问卷调查的网站好wordpress七比2
  • 西双版纳网站制作公司临沂企业网站建站模板
  • 培训做网站国内适合个人做外贸的网站有哪些
  • 我想卖自己做的鞋子 上哪个网站好中信银行网站怎么做的怎么烂
  • 在线网站建设工程标准godaddy 上传网站
  • 营销型网站方案ppt模板手机建站平台微点
  • 网站信息备案管理系统电商网页精品欣赏网站
  • 推广公司让实名认证怎么办系统优化设置
  • 公司网站 正式上线如何创建一个软件