文章目录
jdbcUtil的书写
1、拥有获取连接的方法
2、传入sql进行更新的方法
3、传入sql进行查询的方法
4、关闭的方法
jdbc1.0
import java.sql.*;
//基础的jdbc连接工具类
public class JDBCutil1 {
private String url;//数据库连接url
private String username;//数据库连接账号
private String password;//数据库连接密码
public JDBCutil1(String url, String username, String password) {
this.url = url;
this.username = username;
this.password = password;
}
//返回一个新的连接
public Connection getCon() {
Connection con = null;
try {
Class.forName("com.mysql.jdbc.Driver");//会在每次调用时都被执行 但整个程序运行期间执行一次即可
con = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
//更新方法
//不能解决事务的更新操作
//如果执行的sql没有占位符也需要创建object数组传入
public int dml(String sql,Object obj[]) {
Connection con = getCon();//获取连接
try {
PreparedStatement ps = con.prepareStatement(sql);
for (int i=0;i<obj.length;i++){
ps.setObject(i+1,obj[i]);
}
return ps.executeUpdate();
}catch (Exception e){
e.printStackTrace();
return 0;
}finally {
close(con);
}
}
//查询方法
//需要调用方自己处理结果并关闭
public ResultSet dql(String sql,Object obj[]) {
Connection con = getCon();//获取连接
try {
PreparedStatement ps = con.prepareStatement(sql);
for (int i=0;i<obj.length;i++){
ps.setObject(i+1,obj[i]);
}
return ps.executeQuery();
}catch (Exception e){
e.printStackTrace();
return null;
}
}
private void close(Connection con){
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public void close(ResultSet rs,Connection con){
try {
rs.close();
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
jdbc2.0
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
//基础的jdbc连接工具类
public class JDBCutil2 {
private String url;//数据库连接url
private String username;//数据库连接账号
private String password;//数据库连接密码
public JDBCutil2(String url, String username, String password) {
this.url = url;
this.username = username;
this.password = password;
}
//会在每次调用时都被执行 但整个程序运行期间执行一次即可
//解决方案使用静态代码块进行执行
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//返回一个新的连接
public Connection getCon() {
Connection con = null;
try {
con = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
//更新方法
//如果执行的sql没有占位符也需要创建object数组传入
//解决方案:使用不确定参数作为数据进行传入
public int dml(String sql,Object ... obj) {
Connection con = getCon();//获取连接
try {
PreparedStatement ps = con.prepareStatement(sql);
for (int i=0;i<obj.length;i++){
ps.setObject(i+1,obj[i]);
}
return ps.executeUpdate();
}catch (Exception e){
e.printStackTrace();
return 0;
}finally {
close(con);
}
}
//不能解决事务的更新操作
//解决方案:重载方法不获取新的连接 而是由参数传入同一个连接进行事务操作
public int dml(Connection con,String sql,Object ... obj) throws SQLException {
con.setAutoCommit(false);
PreparedStatement ps = con.prepareStatement(sql);
for (int i=0;i<obj.length;i++){
ps.setObject(i+1,obj[i]);
}
return ps.executeUpdate();
}
//查询方法
//需要调用方自己处理结果并关闭
//使用不确定参数替代数组
//思考怎样才能将不同sql的数据保存至相应的对象集合中
//集合使用的是泛型 引入泛型的概念
//引入反射的概念
public <E> ArrayList<E> dql(String sql,Class<E> c, Object ...obj) {
Connection con = getCon();//获取连接
ArrayList<E> list=new ArrayList<>();
ResultSet rs=null;
try {
PreparedStatement ps = con.prepareStatement(sql);
for (int i=0;i<obj.length;i++){
ps.setObject(i+1,obj[i]);
}
ResultSetMetaData metaData = ps.getMetaData();//获取查询元数据
//元数据中包含所有关于本次sql查询的数据(不包含结果数据)
//获取查询结果返回数据列的数目
int columnCount = metaData.getColumnCount();
//创建对应长度的数组用于保存相应的列名
String [] colimNameArr=new String[columnCount];
//循环获取指定列名名存储至数组中
for (int i=0;i<colimNameArr.length;i++){
// colimNameArr[i]=metaData.getColumnName(i+1);
colimNameArr[i]=metaData.getColumnLabel(i+1);
}
rs = ps.executeQuery();
while(rs.next()){
//使用反射调用泛型类的无参构造方法创建对象
E e= c.newInstance();
//数组循环获取对应列的数据
for (String colName:colimNameArr) {
Object value = rs.getObject(colName);//获取指定列的数据
//使用反射获取指定属性
//获取代表当前列 指定类的属性类型
//获取指定名称的代表指定属性的类型对象
Field declaredField = c.getDeclaredField(colName);
//为指定属性的类型对象授权 (私有属性必须授权后才能使用)
declaredField.setAccessible(true);
//为指定对象 对应属性赋值
declaredField.set(e,value);
}
list.add(e);
}
return list;
}catch (Exception e){
e.printStackTrace();
return null;
}finally {
close(rs,con);
}
}
public void close(Connection con){
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public void close(ResultSet rs,Connection con){
try {
rs.close();
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
已经可以用于简单的使用,但是一些功能仍需要完善,例如连接的获取与关闭。
引入数据库连接池与数据源的概念
连接池的作用与概念
将每个连接的生命周期(创建、使用、销毁)交于连接池进行管理。
因为使用连接池后获取连接不在使用driverManger,所以将从连接池获取连接的过程也称为从数据源获取连接
连接池的实现:读取配置文件获取配置信息,连接数据库先创建多个连接,当我们需要使用连接时可以直接获取不需要再创建,连接池会通过配置对我们使用的连接进行观察,当连接到达配置的时间后自动回收,等待其他获取连接请求
1、导入相应的jar包
2、在src下创建c3p0-config.xml 数据库连接池配置文件
c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- 这是默认配置信息 -->
<default-config>
<!-- 连接四大参数配置 -->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/javatest?characterEncoding=UTF-8</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 池参数配置 -->
<!-- 如果池中数据连接不够时一次增长多少个 -->
<property name="acquireIncrement">5</property>
<!-- 初始化数据库连接池时连接的数量 -->
<property name="initialPoolSize">20</property>
<!-- 数据库连接池中的最大的数据库连接数 -->
<property name="maxPoolSize">25</property>
<!-- 数据库连接池中的最小的数据库连接数 -->
<property name="minPoolSize">5</property>
<!-- 客户获取使用连接最大时间 默认为0 无限 单位s -->
<property name="maxConnectionAge">0</property>
<!-- 客户获取使用连接最大空闲时间 默认为0 无限 单位s -->
<!-- 如果客户距离上次查询已经过了3000秒 那么自动回收连接 -->
<property name="maxIdleTime">3000</property>
<!-- 存在连接池中的连接在指定时间没有客户获取使用时自动销毁 -->
<!-- 默认为0 无限 单位s 必须设置最小连接数 并且客户最大空闲时间不为0 且大于客户最大连接时间 -->
<property name="maxIdleTimeExcessConnections">30000</property>
</default-config>
</c3p0-config>
3、创建数据库连接池对象获取连接
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Test {
public static void main(String[] args) throws SQLException {
//创建c3p0数据库连接池数据源对象
//会自动加载src下c3p0-cinfig.xml配置文件读取配置信息
ComboPooledDataSource dpds=new ComboPooledDataSource();
Connection con = dpds.getConnection();
//使用连接进行jdbc操作
PreparedStatement ps = con.prepareStatement("update account set username='11'");
int i = ps.executeUpdate();
System.out.println(i);
}
}
jdbc3.0
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
//基础的jdbc连接工具类
public class JDBCutil3 {
//使用数据库连接池不需要声明变量保存url等信息 书写在连接池配置文件中
//创建连接池静态对象
private static ComboPooledDataSource dpds;
// private String url;//数据库连接url
// private String username;//数据库连接账号
// private String password;//数据库连接密码
// public JDBCutil3(String url, String username, String password) {
// this.url = url;
// this.username = username;
// this.password = password;
// }
static {
//创建连接池对象加载配置文件
dpds=new ComboPooledDataSource();
// try {
// Class.forName("com.mysql.jdbc.Driver");
// } catch (ClassNotFoundException e) {
// e.printStackTrace();
// }
}
//返回一个新的连接
public static Connection getCon() {
Connection con = null;
try {
//使用连接池获取连接
con=dpds.getConnection();
// con = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
//更新方法
//如果执行的sql没有占位符也需要创建object数组传入
//解决方案:使用不确定参数作为数据进行传入
public static int dml(String sql,Object ... obj) {
Connection con = getCon();//获取连接
try {
PreparedStatement ps = con.prepareStatement(sql);
for (int i=0;i<obj.length;i++){
ps.setObject(i+1,obj[i]);
}
return ps.executeUpdate();
}catch (Exception e){
e.printStackTrace();
return 0;
}finally {
close(con);
}
}
//不能解决事务的更新操作
//解决方案:重载方法不获取新的连接 而是由参数传入同一个连接进行事务操作
public static int dml(Connection con,String sql,Object ... obj) throws SQLException {
con.setAutoCommit(false);
PreparedStatement ps = con.prepareStatement(sql);
for (int i=0;i<obj.length;i++){
ps.setObject(i+1,obj[i]);
}
return ps.executeUpdate();
}
//查询方法
//需要调用方自己处理结果并关闭
//使用不确定参数替代数组
//思考怎样才能将不同sql的数据保存至相应的对象集合中
//集合使用的是泛型 引入泛型的概念
//引入反射的概念
public static <E> ArrayList<E> dql(String sql,Class<E> c, Object ...obj) {
Connection con = getCon();//获取连接
ArrayList<E> list=new ArrayList<>();
ResultSet rs=null;
try {
PreparedStatement ps = con.prepareStatement(sql);
for (int i=0;i<obj.length;i++){
ps.setObject(i+1,obj[i]);
}
ResultSetMetaData metaData = ps.getMetaData();//获取查询元数据
//元数据中包含所有关于本次sql查询的数据(不包含结果数据)
//获取查询结果返回数据列的数目
int columnCount = metaData.getColumnCount();
//创建对应长度的数组用于保存相应的列名
String [] colimNameArr=new String[columnCount];
//循环获取指定列名名存储至数组中
for (int i=0;i<colimNameArr.length;i++){
// colimNameArr[i]=metaData.getColumnName(i+1);
colimNameArr[i]=metaData.getColumnLabel(i+1);
}
rs = ps.executeQuery();
while(rs.next()){
//使用反射调用泛型类的无参构造方法创建对象
E e= c.newInstance();
//数组循环获取对应列的数据
for (String colName:colimNameArr) {
Object value = rs.getObject(colName);//获取指定列的数据
//使用反射获取指定属性
//获取代表当前列 指定类的属性类型
//获取指定名称的代表指定属性的类型对象
Field declaredField = c.getDeclaredField(colName);
//为指定属性的类型对象授权 (私有属性必须授权后才能使用)
declaredField.setAccessible(true);
//为指定对象 对应属性赋值
declaredField.set(e,value);
}
list.add(e);
}
return list;
}catch (Exception e){
e.printStackTrace();
return null;
}finally {
close(rs,con);
}
}
public static void close(Connection con){
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public static void close(ResultSet rs,Connection con){
try {
rs.close();
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
MyJDBCutil
使用泛型、反射、jdbc、代理模式、单例模式、线程池
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
public class MyJDBCutil {
private static ComboPooledDataSource dpds;
static {
//创建连接池对象加载配置文件
dpds=new ComboPooledDataSource();
}
//返回一个新的连接
public static Connection getCon() {
Connection con = null;
try {
//使用连接池获取连接
con=dpds.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
//更新方法
public static int dml(String sql,Object ... obj) {
Connection con = getCon();//获取连接
try {
PreparedStatement ps = con.prepareStatement(sql);
for (int i=0;i<obj.length;i++){
ps.setObject(i+1,obj[i]);
}
return ps.executeUpdate();
}catch (Exception e){
e.printStackTrace();
return 0;
}finally {
close(con);
}
}
//支持事务的更新方法
public static int dml(Connection con,String sql,Object ... obj) throws SQLException {
con.setAutoCommit(false);
PreparedStatement ps = con.prepareStatement(sql);
for (int i=0;i<obj.length;i++){
ps.setObject(i+1,obj[i]);
}
return ps.executeUpdate();
}
//查询方法
public static <E> ArrayList<E> dql(String sql,Class<E> c, Object ...obj) {
Connection con = getCon();//获取连接
ArrayList<E> list=new ArrayList<>();
ResultSet rs=null;
try {
PreparedStatement ps = con.prepareStatement(sql);
for (int i=0;i<obj.length;i++){
ps.setObject(i+1,obj[i]);
}
ResultSetMetaData metaData = ps.getMetaData();//获取查询元数据
//元数据中包含所有关于本次sql查询的数据(不包含结果数据)
//获取查询结果返回数据列的数目
int columnCount = metaData.getColumnCount();
//创建对应长度的数组用于保存相应的列名
String [] colimNameArr=new String[columnCount];
//循环获取指定列名名存储至数组中
for (int i=0;i<colimNameArr.length;i++){
// colimNameArr[i]=metaData.getColumnName(i+1);
colimNameArr[i]=metaData.getColumnLabel(i+1);
}
rs = ps.executeQuery();
while(rs.next()){
//使用反射调用泛型类的无参构造方法创建对象
E e= c.newInstance();
//数组循环获取对应列的数据
for (String colName:colimNameArr) {
Object value = rs.getObject(colName);//获取指定列的数据
//使用反射获取指定属性
//获取代表当前列 指定类的属性类型
//获取指定名称的代表指定属性的类型对象
Field declaredField = c.getDeclaredField(colName);
//为指定属性的类型对象授权 (私有属性必须授权后才能使用)
declaredField.setAccessible(true);
//为指定对象 对应属性赋值
declaredField.set(e,value);
}
list.add(e);
}
return list;
}catch (Exception e){
e.printStackTrace();
return null;
}finally {
close(rs,con);
}
}
//关闭方法
public static void close(Connection con){
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public static void close(ResultSet rs,Connection con){
try {
rs.close();
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
// 自动生成当前连接数据库所有bean对象保存至指定包下
public static void autoGenerateAllBeanS(String beanUrl) {
try {
Connection con = getCon();
String sql = "show tables";
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
autoGenerateFormatBean(rs.getString(1), beanUrl);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void autoGenerateFormatBean(String tables, String beanUrl) {
String sql = "select * from " + tables;
try {
File directory = new File("");// 参数为空
String courseFile = directory.getCanonicalPath();// 获取当前项目路径
String replace = "src/" + beanUrl.replace(".", "/");
String beanNane = tables.toUpperCase().charAt(0) + tables.substring(1);// 当前类名
File file = new File(courseFile, replace + "/" + beanNane + ".java");// 当前类的文件对象
file.createNewFile();
Connection con = getCon();
PreparedStatement ps = con.prepareStatement(sql);
ResultSetMetaData metaData = ps.getMetaData();
// 创建map集合 key为列名 value为对应的java类型
HashMap<String, String> names = new HashMap<>();
// 创建list集合存储所有的属性(顺序)
ArrayList<String> nameList = new ArrayList<>();
for (int i = 0; i < metaData.getColumnCount(); i++) {
String columnLabel = metaData.getColumnLabel(i + 1);// 获取指定列名
String columnTypeName = metaData.getColumnTypeName(i + 1);// 获取列类型
names.put(columnLabel, dbTOjava(columnTypeName));
nameList.add(columnLabel);
}
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw);
// 书写包
bw.write("package " + beanUrl + ";");
bw.newLine();
bw.newLine();
// 书写导入包
bw.write("import java.sql.*;");
bw.newLine();
bw.newLine();
// 书写类名
bw.write("public class " + beanNane + " {");
bw.newLine();
// 生成全部属性
for (String key : nameList) {
String value = names.get(key);
bw.write(" private " + value + " " + key + ";");
bw.newLine();
}
bw.newLine();
// 生成无参构造方法
bw.write(" public " + beanNane + "() {");
bw.newLine();
bw.write(" super();");
bw.newLine();
bw.write(" }");
bw.newLine();
bw.newLine();
// 生成全参构造方法
bw.write(" public " + beanNane + "(");
for (int i = 0; i < nameList.size(); i++) {
String key = nameList.get(i);
if (i != nameList.size() - 1) {
bw.write(names.get(key) + " " + key + ",");
} else {
bw.write(names.get(key) + " " + key);
}
}
bw.write(") {");
bw.newLine();
bw.write(" super();");
bw.newLine();
for (String key : nameList) {
bw.write(" this." + key + " = " + key + ";");
bw.newLine();
}
bw.write(" }");
bw.newLine();
bw.newLine();
// 生成全部属性对应getset方法
for (String key : nameList) {
String value = names.get(key);
bw.write(" public " + value + " get" + key.toUpperCase().charAt(0) + key.substring(1) + "() {");
bw.newLine();
bw.write(" return this." + key + ";");
bw.newLine();
bw.write(" }");
bw.newLine();
bw.newLine();
bw.write(" public void set" + key.toUpperCase().charAt(0) + key.substring(1) + "(" + value + " " + key
+ ") {");
bw.newLine();
bw.write(" this." + key + " = " + key + ";");
bw.newLine();
bw.write(" }");
bw.newLine();
bw.newLine();
}
for (int i = 0; i < nameList.size(); i++) {
String string = nameList.get(i);
nameList.set(i, string + "= \"+ " + string + " + \"");
}
// 生成toString方法
bw.write(" @Override");
bw.newLine();
bw.write(" public String toString() {");
bw.newLine();
bw.write(" return \"" + beanNane + " ");
bw.write(nameList.toString());
bw.write("\";");
bw.newLine();
bw.write(" }");
bw.newLine();
bw.write("}");
bw.flush();
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 转换方法 将数据库列对象转换为指定java类型字符串
private static String dbTOjava(String type) {
if (type.equals("INT")) {
return "int";
} else if (type.equals("VARCHAR")||type.equals("CHAR")) {
return "String";
} else if (type.equals("DOUBLE")||type.equals("FLOAT")) {
return "double";
}else if (type.equals("TIMESTAMP")||type.equals("DATETIME")){
return "Timestamp";
} else {
return "Object";
}
}
}
// MyJDBCutil工具类的使用
//(1)导入相关配置与jar包
//mysql连接jar包
//c3p0jar包 与c3p0配置文件(src下名称固定为c3p0-config.xml)
//(2)修改c3p0连接池配置(url username passwrd)
//(3)将MyJDBCutil工具类创建util包并保存
//(4)创建用于存放数据库数据的bean对象的包com.yunhe.javabean
//(5)使用工具类 MyJDBCutil.autoGenerateAllBeanS(“url”);方法生成工具类
//默认是获取当前运行项目路径下拼接src 如果是空项目创建模块则会导致路径不符创建失败
//(6)准备sql调用对应sql执行方法
//MyJDBCutil.dql(sql,class,obj...);查询方法 返回对应class类型的集合
//obj不确定参数 根据sql中?占位符个数书写
//MyJDBCutil.dml(sql.obj...);更新方法 返回执行sql影响数据条数
//obj不确定参数 根据sql中?占位符个数书写
//MyJDBCutil.dml(con,sql.obj...)更新方法 返回执行sql影响数据条数 需要传入连接进行事务处理
//可以通过工具类 MyJDBCutil.getCon() 方法获取一个新的连接
//在多条sql执行结束后需要手动使用获取的连接对象进行commit或者rollback
//对于从连接池获取的连接而言,调用close方法只是将连接还给连接池
MVC设计模式
Model:数据层
View:视图层
Controller:控制层
模型-视图-控制器(MVC)是一个众所周知的以设计界面应用程序为基础的设计模式。它主要通过分离模型、视图及控制器在应用程序中的角色将业务逻辑从界面中分离
mvc设计模式用于将系统程序中各个应用模块按照指定功能逻辑进行功能划分,保存在不同的位置,实现不同的功能,模块与模块之间相互调用,但功能分明,当系统出现问题时,可以根据问题出现的位置进行快速的修改,在java中对于数据层经常使用dao设计模式进行设计,所以dao就是mvc设计模式的Model层,现在进行数据开发的系统架构基于MVC+DAO设计模式
视图层调用控制层调用相应服务,相应服务调用数据层获取数据,之后由服务层进行解析处理后将数据返回给试图层进行展示
数据层只书写获取数据方法,服务层书写相应服务方法,服务层去决定相应服务需要什么数据调用数据层进行获取