import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
/**
-
@author 超伟
-
@2019年5月29日 下午3:48:26
-
@博客:https://blog.csdn.net/MacWx
*/
public class JdbcUtil {
public static DataSource ds;
public static final ThreadLocal tl = new ThreadLocal();
// 把流操作提取到静态代码块里面。
static {
InputStream in = null;
// 创建连接池对象
try {
// 创建出Properties对象
Properties prop = new Properties();
in = JdbcUtil.class.getResourceAsStream(“/druid.properties”);
// 读取文件中的数据
prop.load(in);
// 创建连接池对象
ds = DruidDataSourceFactory.createDataSource(prop);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
-
@return
*/
public static Connection getConnection() {
//优先从线程中获取连接
Connection conn = tl.get();
// 如果没有拿到这个线程,就说明是业务类在调用
//如果从线程中获取失败,则再新建和数据库的连接
if (conn == null) {
try {
// 用数据库连接池来获取数据库连接
conn = ds.getConnection();
tl.set(conn);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
}
}
return conn;
}
/**
-
@param conn
-
@param ps
-
@param rs
*/
public static void toClose(Connection conn, PreparedStatement ps,
ResultSet rs) {
try {
// 代码不用改,但是含义改变了,把这个连接归还给数据库连接池
// //为了代码的健壮性,需要增加非空判断
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 释放ps对象,关闭资源的时候需要注意顺序,后创建的对象,要先关闭。
try {
if (ps != null) {
ps.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if (conn != null) {
conn.close();
//关闭连接,要从线程中移除
tl.remove();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
-
使用jdbc对于增删改方法的封装
-
对于增删改方法,仍有大部分的冗余代码,但在这些冗余代码中又有一些是不同的
-
例如sql语句,以及传入的参数,所以可把相同的代码封装,不同的代码抽取
-
这只是代码的简化,并不是程序的优化
-
@param sql 对于sql语句的抽取
-
@param obj 可变长参数
-
可变长参数必须是最后一个形参,也只能有一个这样的形参
-
在该方法内部,将obj当成一个数组使用。
-
@throws SQLException
*/
public static void update(String sql,Object…obj) throws SQLException{
Connection conn = null;
PreparedStatement ps = null;
try{
//调用本类中的获取连接方法
conn = getConnection();
ps = conn.prepareStatement(sql);
//再判断传入的参数是否为空
if (obj != null) {
//如果不为空则挨个赋值
for (int i = 0; i < obj.length; i++) {
ps.setObject(i+1, obj[i]);
}
}
ps.executeUpdate();
//这里不用catch异常是因为要在dao中去处理
}finally{
//这里的conn连接不要关,在services层中去关闭!在services中处理事务!
toClose(null, ps, null);
}
}
/*
-
反射:
-
什么是类对象和类的对象?
-
Student s = new Student();
s是类的对象,是某一个类创建出来的对象,这个类是Student
//1.在运行期加载一个类到虚拟机中
Class c = Class.forName(“com.macw.Student”);
//c就是Student的类对象
//2. 通过反射创建Student类的对象
Object o = c.newInstance();
//o 是Student类的对象
//3.获取Student类指定的方法 和 获取所有的方法
Method method = c.getMethod(“方法名”,形参类型);
//method指某一个方法
method.invoke(对象,实参); //动态调用该方法
Method[] methods = c.getMethods();
//methods指类中所有的方法
*/
/**
-
查询多条
-
是用来规范泛型的,
-
@throws SQLException
-
@throws IllegalAccessException
-
@throws InstantiationException
-
@throws InvocationTargetException
-
@throws IllegalArgumentException
*/
public static List select(String sql,Class clz,Object…obj) throws SQLException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
List list = null;
try {
conn = getConnection();
// 1,预加载SQL语句
ps = conn.prepareStatement(sql);
// 2,设置占位符
if (obj != null) {
for (int i = 0; i < obj.length; i++) {
ps.setObject(i+1, obj[i]);
}
}
// 3,执行SQL语句
rs = ps.executeQuery();
// 获取查询结果集中的元数据
// 元数据可以理解为查询结果中的列名
ResultSetMetaData md = rs.getMetaData();
// 获取查询到的列的个数;
int columnCount = md.getColumnCount();
// System.out.println(columnCount);
list = new ArrayList<>();
T t = null;
while(rs.next()){//while每循环一次,代表一行数据。
//clz代表实体类对象,
// 创建实体类的对象
t = clz.newInstance();
for (int i = 0; i < columnCount; i++) {//一行数据有几列就循环几次
// 根据下标获取列名
String columnName = md.getColumnName(i+1);
// 再根据列名获取对应列的值
Object value = rs.getObject(columnName);
// 要将每一列的值赋值给t对象的属性,要要求表中的列名和实体类属性名必须一致!
// 这是通过字符串拼接成 setName();方法
String methodName = “set” + columnName.substring(0, 1).toUpperCase()+
columnName.substring(1).toLowerCase();
// 获取当前实体类中传递过来的所有方法
Method[] methods = clz.getMethods();
// 进行for循环获取所有的set方法
for (Method m : methods) {
// 判断所有的方法中有没有查询结果列名拼成的set方法
// 获取实体类中所有的方法名用:m.getName()方法
if (m.getName().equals(methodName)) {
// Oracle中的number类型对应java中的java.math.BigDecimal类型
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-huRp93mp-1714857790251)]
[外链图片转存中…(img-eA4PZHy9-1714857790252)]
[外链图片转存中…(img-LOeCCjcu-1714857790252)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!