druid、dbutils 桃扇骨 2022-03-25 11:12 189阅读 0赞 相关jar包 ![在这里插入图片描述][20190120162352371.png] 相关数据库 users ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDI0NTc4Nw_size_16_color_FFFFFF_t_70] druid.properties url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true username=root password=123456 driverClassName=com.mysql.jdbc.Driver initialSize=10 maxActive=20 maxWait=1000 utils /* * 问题1:注册驱动,获取连接等写了很多遍 * 问题2:我们每次都从数据库获取新的连接 * mysql是一个TCP/IP协议的网络程序,那么: * (1)每获取一次新的连接的成本很高,需要“三次握手”,断开需要“四次挥手”等过程 * (2)每一个客户端都有单独的线程来维护它的通信 * 这样就会造成如果有很多的客户端同时去连接mysql服务器,会造成 * (1)mysql的并发量就有风险,如果太多就会挂了, * 特别是遇到一些程序员,获取完连接,没有关闭。 * (2)每次高成本获取的连接只用一次,太奢侈了,我们希望可以重复使用连接对象。 * * * 解决: * (1)解决问题1:我们把注册驱动,获取连接等方法,封装到一个工具类中,减少代码 * (2)解决问题2:我们可以使用“数据库连接池”来解决 * * 数据库连接池的技术: * (1)先创建一个连接池pool,然后在池中先放一些连接对象,然后程序去获取连接对象时,用先有的对象,会更快。 * 例如:从自来水新接一桶水,没有从游泳池中直接“装”一桶水快。 * * (2)然后我们可以设置连接池的最大连接数量,如果池中的所有连接都在使用的话,那么可以让“客户端”等待, * 虽然有等待的现象,但是总被“挂”了好。 * * (3)创建连接池时,一开始是初始化少量的连接,等用户并发量上来后,会增加连接数,直到最高连接数为止。 * * (4)之前conn.close()真正的与服务器断开连接,现在从连接池中拿的连接对象,关闭时是还给连接池。 * * 连接池技术有很多,我们讲的是德鲁伊,它是阿里的。 * * 使用步骤: * (1)引入"德鲁伊"jar * druid-1.1.10.jar * * (2)加一个配置文件 * 配置“德鲁伊"连接池的参数 * * 明确:数据库连接池的作用,管理连接。 * 为了获取连接,需要哪些参数:主机名、端口号、用户名、密码、驱动类名 * 其他参数:初始化连接数,最多连接数... * * 在src下建一个druid.properties文件 url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true username=root password=123456 driverClassName=com.mysql.jdbc.Driver initialSize=10 maxActive=20 maxWait=1000 filters=wall * * (3)创建连接池(一个系统一个) * * javax.sql.DataSource * * (4)提供一个方法,可以从数据库连接池中拿连接对象 * (5)提供一个关闭连接的方法 */ public class JdbcUtils { private static DataSource ds ; private static ThreadLocal<Connection> local; static{ try { //静态代码块可以初始化静态变量 // (1)把src下建一个druid.properties文件的数据,加载到一个Properties对象中 Properties pro = new Properties(); pro.load(JdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties")); ds = DruidDataSourceFactory.createDataSource(pro); local = new ThreadLocal<>(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } //这个代码不能保证同一个线程(客户端)共享同一个连接对象,我们后面的代码如果需要事务处理,就有问题 /* public static Connection getConnection() throws SQLException{ //这里只是改变获取连接的代码 return ds.getConnection(); }*/ //这里修改为用ThreadLocal来保存同一个线程的共享变量 public static Connection getConnection() throws Exception{ //这里只是改变获取连接的代码 Connection conn = local.get();//如果从local中能够得到一个连接对象,那么说明当前线程已经拿过了 if(conn == null){//如果不能得到一个连接对象,那么说明当前线程没拿过了 conn = ds.getConnection(); local.set(conn); } return conn; } //提供关闭连接的方法 public static void free(){ try { Connection conn = local.get(); if(conn!=null){ local.remove(); conn.setAutoCommit(true);//还原我们的连接为自动提交模式,等别人再次拿到这个连接时,就可以默认是自动提交 conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } public static DataSource getDs() { return ds; } } BasicDao. (dbutils) /* * apache工具包,有一个ResultSetHandler接口,结果集处理器的接口 * ResultSetHandler接口的实现类们: * (1)BeanListHandler:结果是一个List<T> * (2)BeanHandler:结果是一个Javabean对象 * (3)MapHandler:结果是一行多列,但是又不是Javabean对象 * (4)MapListHandler:结果是多行多列,但是又不是Javabean对象 * (5)ScalarHandler<T>:单个值的封装类型 * */ public class BasicDAO2 { private QueryRunner qr = new QueryRunner(JdbcUtils.getDs()); //适用于insert,update,delete语句 public int update(String sql,Object... args) throws Exception{ return qr.update(sql, args); } //查询多个Javabean public <T> List<T> getList(Class<T> clazz, String sql,Object... args)throws Exception{ return qr.query(sql, new BeanListHandler<T>(clazz), args); } //查询一个Javabean,一般跟着主键,唯一键查询 public <T> T getBean(Class<T> clazz, String sql,Object... args)throws Exception{ return qr.query(sql, new BeanHandler<T>(clazz), args); } //例如:查询总记录数,最高工资,最低工资,平均工资,。。。单个值 public Object queryObject(String sql, Object... args)throws Exception{ return qr.query(sql, new ScalarHandler<>(), args); } //查询多行多列,例如:按部门查询平均工资 public List<Map<String, Object>> queryListMap(String sql, Object... args)throws Exception{ return qr.query(sql, new MapListHandler(), args); } //查询一行多列,例如:查询某一个部门的平均工资 public Map<String, Object> queryMap(String sql, Object... args)throws Exception{ return qr.query(sql, new MapHandler(), args); } } impl 实现类 public class UserDAOImpl extends BasicDAO2 implements UserDAO{ //这个方法根据用户名和密码获取数据库中的记录 @Override public User getUser(User user) { try { String sql = "SELECT * FROM w WHERE username = ? AND `password` = ?"; //查询一个对象 return getBean(User.class, sql, user.getUsername(),user.getPassword()); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } @Override public boolean checkUserName(User user) { try { String sql = "SELECT * FROM users WHERE username = ?"; //查询一个对象 User u = getBean(User.class, sql, user.getUsername()); return u!=null;//如果不为空,说明存在,为true } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } @Override public void saveUser(User user) { try { String sql = "INSERT INTO users VALUES(NULL,?,?,?)"; //查询一个对象 update(sql, user.getUsername(),user.getPassword(),user.getEmail()); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } } Test类 public class TestUserDAO { UserDAOImpl ud = new UserDAOImpl(); @Test public void test1(){ //登录 Scanner input = new Scanner(System.in); System.out.println("用户名:"); String username = input.nextLine(); System.out.println("密码:"); String password = input.nextLine(); User user = new User(username, password); User u = ud.getUser(user); System.out.println(u); } @Test public void test2(){ String username = null; String password = null; //登录 Scanner input = new Scanner(System.in); while(true){ System.out.println("用户名:"); username = input.nextLine(); User user = new User(); user.setUsername(username); //检验这个用户名是否存在 if(!ud.checkUserName(user)){ break; }else{ System.out.println("用户名已存在"); } } while(true){ System.out.println("密码:"); password = input.nextLine(); System.out.println("确认密码:"); String confirm = input.nextLine(); if(password.equals(confirm)){ break; }else{ System.out.println("两次输入密码要一致"); } } System.out.println("邮箱:"); String email = input.nextLine(); User u = new User(); u.setUsername(username); u.setPassword(password); u.setEmail(email); try { //注册,添加到数据库中 ud.saveUser(u); System.out.println("注册成功"); } catch (Exception e) { System.out.println("注册失败"); } } } [20190120162352371.png]: /images/20220325/776375ddece545b9af5c836e61639b95.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDI0NTc4Nw_size_16_color_FFFFFF_t_70]: /images/20220325/56905c9374ed477d99a2bec54ade5b73.png
还没有评论,来说两句吧...