发表于: 2020-05-12 22:07:41

1 1200


最近忙完论文答辩,今天正式来线下试学。

今天完成的事情:了解jdbc,c3p0连接池

一.JDBC的API

1.DriverManager 驱动管理类

主要作用:

1.1注册驱动

实际开发中注册驱动会使用如下的方式:

Class.forName("com.mysq.jdbc.Driver");

//1.加载驱动
DriverManager.registerDriver(new Driver());

JDBC源代码中Driver类

但是在JDBC的Driver类中的静态代码块已经注册过了,再次如上手动调用会导致驱动注册两次。

1.2获得连接

Connection getConnection(String url,String username,String password);

url写法: jdbc:mysql://localhost:3306/jdbc  <jdbc :协议  mysq|:子协议   localhost :主机名  3306 :端口号>

url简写: jdbc:mysq:///jdbc


2.Connection:连接对象

主要作用:

2.1创建执行SQL语句的对象,Connection三个方法

Statement createStatement : 执行SQL语句,有SQL注入的漏洞存在。

PreparedStatement prepareStatement(String sq) : 预编译SQL语句,解决SQL注入的漏洞。

CallableStatement prepareCall(String sql) : 执行SQL中存储过程

2.2进行事务的管理

setAutoCommit(boolean autoCommit) :设置事务是否自动提交。

commit() :事务提交

rollback() :事务回滚


3.Statement : 执行SQL

主要作用:

3.1执行SQL语句,不同返回值用不同的方法

boolean execute(String sql) :执行SQL ,执行select语句返回true,否则返回false

ResultSet executeQuery(String sq) :执行SQL中的select语句,查询

int executeUpdate(String sq|) :执行SQL中的insert/update/delete语句

3.2执行批处理操作,执行一批sql命令

addBatch(String sq) :添加到批处理

executeBatch() :执行批处理

clearBatch() :清空批处理


ResultSet :结果集

结果集:其实就是查询语句( select )语句查询的结果的封装。

主要作用:

结果集获取查询到的结果的。

next() :针对不同的类型的数据可以使用getXXX()获取数据,通用的获取数据的方法:

getObject();

4.jdbc的资源释放

jdbc程序运行结束后,要释放那些和数据库交互的对象,通常就是上面的,ResultSet,Statement和Connection.特别是Connection对象,它是特别稀有的资源,使用原则是晚创建,早释放。

if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
conn = null;
}

二.JDBC的crud

/**
* JDBC的插入操作
*/
@Test
public void demo2(){
Connection conn = null;
Statement st =null;
try{
//1.加载驱动
    Class.forName("com.mysql.jdbc.Driver");
//2.获得连接
    conn = DriverManager.getConnection("jdbc:mysql:///first","root","root");
//3.创建和执行语句
   String sql = "insert into jdbctable values (4,'小四',24)";
st = conn.createStatement();
int i = st.executeUpdate(sql);
if(i>0){
System.out.println("插入成功");
}

}catch(Exception e){
e.printStackTrace();
}finally{

//4.资源的释放
   if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
conn = null;//垃圾回收更早的回收对象
}
}

三.对JDBC的加载驱动和创建连接以及释放资源的公共代码提取成工具类,对参数生成properties文件并加载

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///first
username=root
password=root
public class JDBCUtils {
private static final String driverClass;
private static final String url;
private static final String username;
private static final String password;

static{
//加载属性文件,通常是类的加载器的方式进行获取
        Properties props = new Properties();
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
props.load(is);
} catch (IOException e) {
e.printStackTrace();
}
driverClass = props.getProperty("driverClass");
url = props.getProperty("url");
username = props.getProperty("username");
password = props.getProperty("password");
}
/**
    * 注册驱动的方法
    * @throws ClassNotFoundException
    */
   public static void loadDriver() throws ClassNotFoundException {
Class.forName(driverClass);
}

/**
    * 获得连接
    * @return  conn
    * @throws SQLException
    */
   public static Connection getConnection() throws Exception {
loadDriver();
Connection conn = DriverManager.getConnection(url,username,password);
return conn;
}

public static void release(Connection conn, Statement st){
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
conn = null;
}
if(st != null){
try {
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
st = null;
}
}
public static void release(Connection conn, Statement st, ResultSet rs){
if(rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
rs = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
conn = null;
}
if(st != null){
try {
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
st = null;
}
}
}

四.SQL注入漏洞,当应用在登录时,

在登录时,用户名aaa后面添加数据库的语句  aaa ' or '1=1 和 aaa' --

按照上面JDBC的statement方法,无论密码是多少都会通过,因为会把or判断前面是true,结果为true.  --在SQL语句中为注释

解决SQL注入漏洞:运用PreparedStatement的使用:

PreparedStatement是Statement的子接口,它的实例对象可以通过调用

Connection.preparedStatement(sql)方法获得,相对于Statement对象而言:

       - PreperedStatement可以避免SQL注入的问题。

       - Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率。

       - 并且PreperedStatement对于sq|中的参数 ,允许使用占位符的形式进行替换,简化sq|语句的编写。

public class JDBCDemo5 {
/**
    *删除数据
    */
   @Test
   public void demo(){
Connection conn = null;
PreparedStatement psmt = null;
try {
//获得连接
           conn = JDBCUtils.getConnection();
//编写SQL
           String sql = "delete from jdbctable where id = ?";
//预编译SQL
           psmt = conn.prepareStatement(sql);
//设置参数
           psmt.setInt(1,5);
//执行SQL
           int num = psmt.executeUpdate();
if(num > 0){
System.out.println("运用prepareStatement删除成功!");
}
} catch (Exception e) {
e.printStackTrace();
}finally{
JDBCUtils.release(conn,psmt);
}
}
}

五.c2p0连接池

连接池:连接池是创建和管理一个连接池的缓存池技术,这些连接准备好被任何所需要它们的线程使用。

应用程序直接获取连接的缺点:

用户每次请求都需要向数据库获取连接,而数据库创建连接通常会消耗大量资源。假如一个网站每天有10万的访问量,数据库服务器就需要创建10万次连接,极大的浪费的数据库资源,并且极容易造成数据库的内存溢出。

c3p0的使用:

导入c3p0的jar包

c3p0使用,可以手动设置参数

ComboPooledDataSource dataSource = ComboPooledDataSource(); //创建

dataSource.getConnection();//获得连接池

dataSource.setMaxPoolSize(20)//最大连接数

dataSource.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver 

dataSource.setJdbcUrl( "jdbc:postgresql://localhost/testdb" );

dataSource.setUser("swaldman");                                   

dataSource.setPassword("test-password"); 


明天计划的事情:明天学习JdbcTemplate和mybatis。明天的速度还能再加快点。
遇到的问题:今天被自己一个小BUG卡了下,忘记获取对象,所以运行后一直报空指针异常
收获:今天算是记住了jdbc的运行过程。明天继续加油。


返回列表 返回列表
评论

    分享到