JDBC笔记4

JDBC的ORM技术

什么是ORM?
1)ORM=Object Relationship Database Mapping
2)对象和关系数据库的映射
3)简单说,一个对象,对应数据库里的一条记录
为什么要使用ORM技术?

用JDBC的API编程访问数据库,代码量较大,特别是访问字段较多的表的时候,代码显得繁琐、累赘,容易出错,例如:

public void addAccount(final Account account) throws DAOException {
          final Connection conn=getConnection();
          PreparedStatement pstmt=con.prepareStatment("insert into account value(?,?,?,?,?,?,?,?,?)");
          pstmt.setString(1,account.getUserName());
          pstmt.setInt(2,account.getPassWord());
          pstmt.setString(3,account.getSex());
          pstmt.setString(4,account.getQq());
          ......
          pstmt.execute();
          conn.Close();
       }
//可见,程序员需要耗费大量的时间、精力去编写具体的数据库访问的SQL语句,
//还要十分小心其中大量重复的源代码是否有疏漏,并不能集中精力于业务逻辑开发上面。

ORM则建立了Java对象与数据库对象之间的影射关系,程序员不需要编写复杂的SQL语句,直接操作Java对象即可,从而大大降低了代码量,也使程序员更加专注于业务逻辑的实现。

采用JDBC编程,在很多时候存在效率低下的问题,如:

pstmt =conn.prepareStatement("insert into user_info values(?,?)");
       for (int i=0; i<1000; i++) {
          pstmt.setInt(1,i);
          pstmt.setString(2,"User"+i.toString());
          pstmt.executeUpdate();
       }
//以上程序将向后台数据库发送1000次SQL语句执行请求,运行效率较低.

如果采用ORM技术,ORM框架将根据具体数据库操作需要,会自动延迟向后台数据库发送SQL请求,如上面的程序,只会在循环完成后,一次向数据库发送操作请求,从而大大降低通讯量,提高运行效率;ORM也可以根据实际情况,将数据库访问操作合成,尽量减少不必要的数据库操作请求。

下面是ORM的一个例子,提供方法get(int id),返回一个Hero对象

package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

public class TestJDBC {
	public static Hero get_id(int id) {
		Hero hero = new Hero();
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
    	String url="jdbc:mysql://127.0.0.1:3306/how2j?characterEncoding=UTF-8";
    	String user="root";
    	String password="root";
    	
    	try(
    		Connection c = DriverManager.getConnection(url, user, password);
    		Statement s = c.createStatement();
    		) {
    		
    		String sql = "select * from hero where id = "+id;
    		ResultSet rs = s.executeQuery(sql);
    		if(rs.next()) {
    			hero.id=rs.getInt("id");
    			hero.name=rs.getString("name");
    			hero.hp=rs.getFloat("hp");
    			hero.damage=rs.getInt("damage");
    		}
    		
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			return hero;
		}
	}
	
    public static void main(String[] args) {
    	Hero h=get_id(22);
    	System.out.println(h.id+"  "+h.name+"  "+h.hp+"  "+h.damage);
    }
}


class Hero{
    public int id;
    public String name;
    public float hp;
    public int damage;
}

JDBC的DAO技术

什么是DAO?

DAO=DataAccess Object数据访问对象

实际上就是把数据库相关的操作都封装在这个类里面,其他地方看不到JDBC的代码

新建一个接口DAO,里面有几个空方法

package jdbc;

import java.util.List;

public interface DAO {
	//增加
    public void add(Hero hero);
    //修改
    public void update(Hero hero);
    //删除
    public void delete(int id);
    //获取
    public Hero get(int id);
    //查询
    public List<Hero> list();
    //分页查询
    public List<Hero> list(int start, int count);
}

然后在类HeroDAO中去实现这个方法

package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import jdbc.Hero;
  
public class HeroDAO implements DAO{
    public HeroDAO() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public Connection getConnection() throws SQLException {
        return DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2j?characterEncoding=UTF-8", "root",
                "root");
    }
    public int getTotal() {
        int total = 0;
        try (Connection c = getConnection(); Statement s = c.createStatement();) {
            String sql = "select count(*) from hero";
            ResultSet rs = s.executeQuery(sql);
            while (rs.next()) {
                total = rs.getInt(1);
            }
            System.out.println("total:" + total);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return total;
    }
    public void add(Hero hero) {
        String sql = "insert into hero values(null,?,?,?)";
        try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {
            ps.setString(1, hero.name);
            ps.setFloat(2, hero.hp);
            ps.setInt(3, hero.damage);
            ps.execute();
            ResultSet rs = ps.getGeneratedKeys();
            if (rs.next()) {
                int id = rs.getInt(1);
                hero.id = id;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    public void update(Hero hero) {
        String sql = "update hero set name= ?, hp = ? , damage = ? where id = ?";
        try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {
            ps.setString(1, hero.name);
            ps.setFloat(2, hero.hp);
            ps.setInt(3, hero.damage);
            ps.setInt(4, hero.id);
            ps.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    public void delete(int id) {
        try (Connection c = getConnection(); Statement s = c.createStatement();) {
            String sql = "delete from hero where id = " + id;
            s.execute(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
  
    public Hero get(int id) {
        Hero hero = null;
        try (Connection c = getConnection(); Statement s = c.createStatement();) {
            String sql = "select * from hero where id = " + id;
            ResultSet rs = s.executeQuery(sql);
            if (rs.next()) {
                hero = new Hero();
                String name = rs.getString(2);
                float hp = rs.getFloat("hp");
                int damage = rs.getInt(4);
                hero.name = name;
                hero.hp = hp;
                hero.damage = damage;
                hero.id = id;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return hero;
    }
    public List<Hero> list() {
        return list(0, Short.MAX_VALUE);
    }
    public List<Hero> list(int start, int count) {
        List<Hero> heros = new ArrayList<Hero>();
        String sql = "select * from hero order by id desc limit ?,? ";
        try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {
            ps.setInt(1, start);
            ps.setInt(2, count);
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                Hero hero = new Hero();
                int id = rs.getInt(1);
                String name = rs.getString(2);
                float hp = rs.getFloat("hp");
                int damage = rs.getInt(4);
                hero.id = id;
                hero.name = name;
                hero.hp = hp;
                hero.damage = damage;
                heros.add(hero);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return heros;
    }
}

数据库连接池

传统方式
1)当有多个线程,每个线程都需要连接数据库执行SQL语句的话,那么每个线程都会创建一个连接,并且在使用完毕后,关闭连接。

2)创建连接和关闭连接的过程也是比较消耗时间的,当多线程并发的时候,系统就会变得很卡顿。

3)同时,一个数据库同时支持的连接总数也是有限的,如果多线程并发量很大,那么数据库连接的总数就会被消耗光,后续线程发起的数据库连接就会失败。

在这里插入图片描述

使用连接池方式
1)与传统方式不同,在使用连接之前,就会在连接池内创建好一定数量的连接。
2)如果有任何线程需要使用连接,那么就从连接池里面借用,而不是自己重新创建.
3)使用完毕后,又把这个连接归还给连接池供下一次或者其他线程使用。
4)倘若发生多线程并发情况,连接池里的连接被借用光了,那么其他线程就会临时等待,直到有连接被归还回来,再继续使用。
5)整个过程,这些连接都不会被关闭,而是不断的被循环使用,从而节约了启动和关闭连接的时间。

在这里插入图片描述

使用DBCP和C3P0连接池

在使用之前先导入一些jar包,见下图,导入方式见JDBC笔记1,具体的包百度下载。

在这里插入图片描述

初始化dbcp连接池
package jdbc;

import org.apache.commons.dbcp2.BasicDataSource;

public class DBCP {
	static String url="jdbc:mysql://127.0.0.1:3306/how2j?characterEncoding=UTF-8";
	static String user="root";
	static String password="root";
	
	//初始化JDBC连接池,初始化必须最先执行,所以放在静态代码块中
	static {
		BasicDataSource ds = new BasicDataSource();
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		ds.setUrl(url);
		ds.setUsername(user);
		ds.setPassword(password);
		
		ds.setInitialSize(5);//设置连接池初始化的时候有5个连接
		ds.setMinIdle(3);//设置连接池最小的空闲连接,比如初始的5个连接用完了3个,空闲的还有两个,那么再创建一个保持在3个空闲连接,避免突发大量连接到来新创建连接降低性能
		ds.setMaxTotal(20);//设置最大连接数,如果没有这个限制,当大量连接到来,无限制的创建连接,设备可能承受不了
	}
}
从连接池获取连接
package jdbc;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbcp2.BasicDataSource;

public class DBCP {
	static String url="jdbc:mysql://127.0.0.1:3306/how2j?characterEncoding=UTF-8";
	static String user="root";
	static String password="root";
	static BasicDataSource ds = null;
	static {
		ds = new BasicDataSource();
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		ds.setUrl(url);
		ds.setUsername(user);
		ds.setPassword(password);
		
		ds.setInitialSize(5);
		ds.setMinIdle(3);
		ds.setMaxTotal(20);
	}
	
	//创建一个方法,从连接池获取连接
	public static Connection getConnection() throws SQLException {
		return ds.getConnection();
	}
}
使用获取的连接&释放连接
package jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

public class TestJDBC {
    public static void main(String[] args) throws Exception {
    	Connection con = DBCP.getConnection();
    	Statement s = con.createStatement();
        String sql = "select * from hero where id = 13";
        ResultSet rs = s.executeQuery(sql);
        while(rs.next()) {
        	int id = rs.getInt(1);
        	String name = rs.getNString(2);
        	float hp = rs.getFloat(3);
        	int damage = rs.getInt(4);
        	System.out.println(id+"  "+name+"  "+hp+"  "+damage);
        }
        s.close();
        con.close();//从连接池获取的连接,使用完毕后直接close会归还到连接池
    }
}
c3p0

使用方式和dbcp一样,只是内部有区别,功能更强大,也更常用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值