Java学习十四,JDBC,反射
目录
1.JDBC入门
1.1.JDBC的概念
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
1.1 JDBC的基本操作
1.我们先创建数据库jdbctest
2.我们创建demo.java来操作数据库
package jdbc;
import org.junit.Test;
import java.sql.*;
public class demo1 {
private ResultSet res = null;
private Statement statement = null;
private Connection connection = null;
/**
* JDBC的入门程序
*/
@Test
public void demo() {
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获得连接 jdbc:mysql://地址:端口/数据库名称
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest", "root", "root");
//3.创建执行sql语句的对象,并且执行sql
String sql = "select * from user";
statement = connection.createStatement(); //创建执行的对象
res = statement.executeQuery(sql); //执行sql
//输出
while (res.next()) {
int id = res.getInt("uid");
String name = res.getString("name");
String username = res.getString("username");
String password = res.getString("password");
System.out.println("id:" + id + " name:" + name + " username:" + username + " password:" + password);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//4.释放资源
try {
res.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
1.2 JDBC的API
-
DriverManager类
作用:
1. 注册驱动:Class.forName("com.mysql.jdbc.Driver");
2. 获得连接 :Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest", "root", "root");
-
Connection类
作用:
1. 创建执行SQL语句的对象:
Statement createStatement(); 执行sql语句,有依赖注入的风险
PreparedStatement prepareStatement(sql); 预编译sql语句,解决依赖注入问题
CallableStatement prepareCall(sql); 执行sql存储过程
2. 事务的管理
connection.setAutoCommit(false); 设置事务是否自动提交
connection.commit(); 事务提交
connection.rollback(); 事务回滚 -
Statement类
作用:
1. 执行sql语句
ResultSet res = statement.executeQuery(sql); 执行select语句,返回结果
boolean execute = statement.execute(sql); 执行select语句,成功返回true
int i = statement.executeUpdate(sql); 执行sql中的select/insert/update语句
2. 执行批量操作
statement.addBatch(sql); 批量任务的添加
statement.executeBatch(); 批量任务的执行
statement.clearBatch(); 批量任务的清除 -
ResultSet类
作用:获取结果集(其实就是获得查询语句的结果封装)
1.3 JDBC的CRUD操作(createStatement类)
package jdbc;
import org.junit.Test;
import java.sql.*;
public class crud {
private Statement statement = null;
private Connection connection = null;
private ResultSet resultSet = null;
/**
* JDBC查询所有
*/
@Test
public void select(){
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获得连接 jdbc:mysql://地址:端口/数据库名称
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest", "root", "root");
//3.创建执行sql语句的对象,并且执行sql
String sql = "select * from user";
statement = connection.createStatement(); //创建执行的对象
resultSet = statement.executeQuery(sql); //执行sql
//输出
while (resultSet.next()) {
int id = resultSet.getInt("uid");
String name = resultSet.getString("name");
String username = resultSet.getString("username");
String password = resultSet.getString("password");
System.out.println("id:" + id + " name:" + name + " username:" + username + " password:" + password);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//4.释放资源
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* JDBC的修改
*/
@Test
public void del() {
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获得连接 jdbc:mysql://地址:端口/数据库名称
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest", "root", "root");
//3.创建执行sql语句的对象,并且执行sql
statement = connection.createStatement(); //创建执行的对象
String sql = "delete from user where uid='3'";
int res = statement.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
} finally {
//4.释放资源
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* JDBC的修改
*/
@Test
public void update() {
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获得连接 jdbc:mysql://地址:端口/数据库名称
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest", "root", "root");
//3.创建执行sql语句的对象,并且执行sql
statement = connection.createStatement(); //创建执行的对象
String sql = "update user set username='222222' where name='33'";
int res = statement.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
} finally {
//4.释放资源
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* JDBC的添加
*/
@Test
public void add() {
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获得连接 jdbc:mysql://地址:端口/数据库名称
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest", "root", "root");
//3.创建执行sql语句的对象,并且执行sql
statement = connection.createStatement(); //创建执行的对象
String sql = "insert into user values (null,'11','22','33')";
int res = statement.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
} finally {
//4.释放资源
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
1.4 JDBC防sql注入(prepareStatement类)
package jdbc;
import org.junit.Test;
import java.sql.*;
public class crud {
private Statement statement = null;
private Connection connection = null;
private ResultSet resultSet = null;
/**
* 防止sql注入
*/
public void security_sql(String usernames,String passwords) {
PreparedStatement pst=null;
try {
//获取连接
connection = gongju.lianjie();
//编写sql
String sql = "select * from user where username=? and password=?";
//预处理sql
pst= connection.prepareStatement(sql);
pst.setString(1,usernames);
pst.setString(2,passwords);
//执行sql
pst.executeQuery(sql);
//输出
while (resultSet.next()) {
int id = resultSet.getInt("uid");
String name = resultSet.getString("name");
String username = resultSet.getString("username");
String password = resultSet.getString("password");
System.out.println("id:" + id + " name:" + name + " username:" + username + " password:" + password);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
gongju.close(resultSet, statement, connection);
}
}
}
1.5 JDBC连接池
首先必须创建c3p0-config.xml
(名字不能随意)
<?xml version='1.0' encoding='UTF-8'?>
<c3p0-config>
<!--mysql的配置-->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbctest</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">10</property>
<property name="maxPoolSize">100</property>
</default-config>
</c3p0-config>
其次便可以连接使用了
package jdbc;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.Test;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class lianjiechi {
/**
* 手动设置连接池
*/
@Test
public void demo() {
Connection con = null;
PreparedStatement pstm = null;
ResultSet rel = null;
try {
//创建连接池
ComboPooledDataSource datasource = new ComboPooledDataSource();
//设置连接池的参数
datasource.setDriverClass("com.mysql.jdbc.Driver");
datasource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbctest");
datasource.setUser("root");
datasource.setPassword("root");
datasource.setInitialPoolSize(2); //启动初始连接数
datasource.setMaxPoolSize(20); //最大连接数
//获得连接
con = datasource.getConnection();
//编写sql
String sql = "select * from user";
//预编译sql
pstm = con.prepareStatement(sql);
rel = pstm.executeQuery();
//输出
while (rel.next()) {
System.out.println(rel.getInt("uid") + " " + rel.getString("name"));
}
} catch (PropertyVetoException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 使用位置文件的方式
*/
@Test
public void demo1() {
Connection con = null;
PreparedStatement pstm = null;
ResultSet rel = null;
try {
//创建连接池
ComboPooledDataSource datasource = new ComboPooledDataSource();
//获得连接
con = datasource.getConnection();
//编写sql
String sql = "select * from user";
//预编译sql
pstm = con.prepareStatement(sql);
rel = pstm.executeQuery();
//输出
while (rel.next()) {
System.out.println(rel.getInt("uid") + " " + rel.getString("name")+" "+rel.getString("Username"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
2.反射入门
2.1 反射的概述
JAVA反射机制是在运行状态中
,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态
获取信息以及动态
调用对象方法的功能称为java语言的反射机制。
2.2 反射的作用
在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放
,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法
。当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后在最终返回结果的地方对应用的权限进行了校验,对于没有权限的应用返回值是没有意义的缺省值,否则返回实际值起到保护用户的隐私目的。
2.3 反射常用对象
类名 | 用途 |
---|---|
Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Constructor类 | 代表类的构造方法 |
Field类 | 代表类的成员变量(成员变量也称为类的属性) |
Method类 | 代表类的方法 |
2.3.1 Class类
获取Class类的方法有3种:
- 通过类名.class;
- 对象.getclass();
- class.forName();
常用
Class类代表某个类的字节码,并提供了加载字节码的方法:forName("包名.类名")
,forName用于加载字节码到内存中,并封装成一个对象;
package fanshe;
import org.junit.Test;
public class demo {
/**
* 获取class的方法
* 1. 通过类名.class;
* 2. 对象.getclass();
* 3. class.forName();
*/
@Test
public void demo1() {
//1.通过类名.class;
Class<person> personClass1 = person.class;
//2. 对象.getclass();
Class<person> personClass2 = (Class<person>) new person().getClass();
//3. class.forName();
try {
Class personClass3 = Class.forName("fanshe.person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
2.3.2 Constructor类
方法 | 用途 |
---|---|
newInstance(Object… initargs) | 根据传递的参数创建类的对象 |
package fanshe;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class demo {
@Test
public void demo2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class aClass = Class.forName("fanshe.person");
Constructor c = aClass.getConstructor();
person person = (fanshe.person) c.newInstance(); //相当于person person=new person();
System.out.println(person.eat());
}
@Test
public void demo3() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> aClass = Class.forName("fanshe.person");
Constructor<?> c = aClass.getConstructor(String.class, String.class);
person person= (fanshe.person) c.newInstance("轩轩","女"); //相当于person person=new person("轩轩","女");
System.out.println(person.eat());
}
}
分别运行demo2和demo3,得到结果不同:
2.3.3 Field类
方法 | 用途 |
---|---|
setAccessible(boolean) | 设置变量是否可以访问 |
getField(String name) | 获得某个公有的属性对象 |
getFields() | 获得所有公有的属性对象(包含父类) |
getDeclaredField(String name) | 获得某个属性对象 |
getDeclaredFields() | 获得所有属性对象 |
package fanshe;
import org.junit.Test;
import java.lang.reflect.Field;
public class demo {
/**
* Field类
* 操作公有属性和私有属性
*/
@Test
public void demo4() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
//获得class
Class<?> aClass = Class.forName("fanshe.person");
person p = (person) aClass.newInstance(); //默认调用无参构造
//获取属性
Field name = aClass.getField("name");
//操作属性
name.set(p, "李四");
System.out.println(name.get(p));
}
@Test
public void demo5() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
//获取class
Class<?> aClass = Class.forName("fanshe.person");
person p = (person) aClass.newInstance();
//获取属性
Field sex = aClass.getDeclaredField("sex");
//设置可以被操作
sex.setAccessible(true);
sex.set(p,"不男不女");
System.out.println(sex.get(p));
}
}
2.3.4 Method类
方法 | 用途 |
---|---|
getMethod(String name, Class…<?> parameterTypes) | 获得该类某个公有的方法 |
getMethods() | 获得该类所有公有的方法 |
getDeclaredMethod(String name, Class…<?> parameterTypes) | 获得该类某个方法 |
getDeclaredMethods() | 获得该类所有方法 |
invoke(Object obj, Object… args) | 传递object对象及参数调用该对象对应的方法 |
package fanshe;
import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class demo {
/**
* Method类
* 操作公有方法和私有方法
*/
@Test
public void demo6() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class<?> aClass = Class.forName("fanshe.person");
//实例化
person p = (person) aClass.newInstance();
//获取属性
Field name = aClass.getField("name");
name.set(p, "花花");
//获取共有方法
Method eat = aClass.getMethod("eat");
//执行方法
System.out.println(eat.invoke(p));
}
@Test
public void demo7() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
Class<?> aClass = Class.forName("fanshe.person");
//实例化
person p = (person) aClass.newInstance();
//获取私有方法
Method run = aClass.getDeclaredMethod("run",String.class);
run.setAccessible(true);
System.out.println(run.invoke(p,"小花蛤"));
}
}