当前位置: 首页 > news >正文

Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)

文章目录

  • 1 JDBC(Java Database Connectivity)
    • 1.1 什么是 JDBC?
    • 1.2 JDBC 核心思想
  • 2 JDBC开发步骤【重点】
    • 2.0 环境准备
    • 2.1 注册数据库驱动
    • 2.2 获取数据库的连接
    • 2.3 获取数据库操作对象Statement
    • 2.4 通过Statement对象执行SQL语句
    • 2.5 处理返回结果
    • 2.6 释放资源
  • 3 ResultSet结果集
    • 3.1 查询案例
  • 四、综合案例【登录】
    • 4.1 登录分析
    • 4.2 登录案例实现
    • 4.3 登录案例分析-SQL注入问题
    • 4.4 登录案例更新
    • 4.5 PreparedStatement
  • 五、ORM映射
        • 5.1 思想
    • 5.2 实体类的规范
    • 5.3 代码实现
  • 6 封装工具类
    • 6.1 代码实现
    • 6.2 工具类测试
  • 7 DAO (Data Access Object)
    • 7.1 开发流程
      • 7.1.1 EmpDao接口
      • 7.1.2 实体类
      • 7.1.3 EmpDao实现类
      • 7.1.4 测试类
  • 8 Service 业务 【掌握】
    • 8.1 什么是业务
    • 8.2 转账业务开发
  • 9 事务
    • 9.1 转账业务实现
    • 9.2 解决方案1:传递 Connection
    • 9.3 解决方案2:ThreadLocal
    • 9.4 使用ThreadLocal更新JDBC工具类
    • 9.5 事务封装
    • 9.6 最终的转账业务
  • 10 三层架构【理解】
  • 11 单元测试
    • 11.1 单元测试
    • 11.2 实际应用
  • 12 连接池【理解掌握】
    • 12.1 Druid连接池
    • 12.2 db.properties
    • 12.3 最终版JDBC工具类
    • 12.4 连接池测试
  • 14 DaoUtils工具类【理解】
    • 13.1 工具类实现
    • 13.2 DaoUtils工具类使用
  • 14 DBUtils工具类
    • 14.1 DBUtils简介
        • 14.2 DbUtils核心API
    • 14.3 DbUtils的使用步骤
    • 14.4 DBUtils使用
    • 14.5 字段与属性名不一致
  • 15 Lombok插件

1 JDBC(Java Database Connectivity)

1.1 什么是 JDBC?

JDBC(Java Database Connectivity) Java 连接数据库的规范(标准),可以使用 Java 语言连接数据库完成 CRUD 操作

1.2 JDBC 核心思想

Java 中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类(Driver 数据库驱动)。

JDBC核心思想
在这里插入图片描述

2 JDBC开发步骤【重点】

/*** JDBC的开发步骤:*    0、准备工作*         a、准备数据库和数据表*         b、导入jar包* 			 	    1、在工程下新建一个lib的文件,将驱动jar包放入到文件夹中 *  			  	2、右击jar包---> add as library*                  注意:类路径(classpath) 就是java代码生成.class文件的路径*    1、注册驱动*    2、获取数据库连接对象Connection*    3、获取数据库操作对象*    4、通过数据库操作对象执行SQL语句*    5、处理结果*    6、释放资源*/

2.0 环境准备

环境准备

  • a、将数据库连接驱动包赋值到当前工程的lib文件夹下
  • b、将jar包添加到类路径(class文件生成的位置)中。右击jar包 —> add as library

2.1 注册数据库驱动

//1、注册数据库驱动
//实现方式一:不推荐使用
//Driver driver = new Driver();
//DriverManager.registerDriver(driver);
//实现方式二:推荐使用
Class.forName("com.mysql.jdbc.Driver");//主动触发类加载,执行静态代码块,进而注册驱动

2.2 获取数据库的连接

协议://地址:端口号

  • mysql 5.7版本 jdbc:mysql://localhost:3306/数据库名
    • mysql 8.x版本 需要加上指定时区 jdbc:mysql://localhost:3306/数据库名?serverTimezone=?serverTimezone = UTC (北京时间)
    • jdbc:mysql://localhost:3306/数据库名?serverTimezone=?serverTimezone = Asia/shanghai (j精确到时分秒时间)
  • 本机数据库localhost:3306可以省略不写,即 jdbc:mysql:///数据库名
 // 2、获取数据库连接对象Connection
/*** 网络编程三要素*      协议+地址+端口*      jdbc:mysql://localhost:3306/数据库名?serverTimezone=UTC*/      
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2303", "root", "123456");

2.3 获取数据库操作对象Statement

// 3、获取数据库操作对象
Statement statement = conn.createStatement();

2.4 通过Statement对象执行SQL语句

// 4、通过数据库操作对象执行SQL语句
int count = statement.executeUpdate("insert into emp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (6666,'张三','java',7369,'2021-05-01',30000,200,30)");

2.5 处理返回结果

// 5、处理结果
if(count > 0){System.out.println("插入成功!!");
}else{System.out.println("插入失败!!");
}

2.6 释放资源

//6、释放资源
statement.close();
conn.close();

3 ResultSet结果集

//5、处理结果集
/*** ResultSet提供了一组方法*          next(); 判断是否有下一行数据,如果有返回true,并将游标移动到下一行*          getXXX("字段名");    XXX表示字段在java中的对应的类型*          getXXX(列的下标);    XXX表示字段在java中的对应的类型*/

3.1 查询案例

查询emp表的数据

while(rs.next()){int empno = rs.getInt("empno");//int empno = rs.getInt(1);System.out.println(empno);String ename = rs.getString("ename");System.out.println(ename);String job = rs.getString("job");System.out.println(job);Date hiredate = rs.getDate("hiredate");System.out.println(hiredate);double sal = rs.getDouble("sal");System.out.println(sal);
}

四、综合案例【登录】

4.1 登录分析

/*** 登录的思路:*      1、根据用户输入的用户名和密码到数据库中查询*          select * from tb_user where username = "你输入的用户名" and password = "你输入的密码"*          select * from tb_user where username = admin and password = 123*          如果有结果:登录成功*          如果没有结果:登录失败*/

4.2 登录案例实现

public class JDBCDemo05 {    public static void main(String[] args) throws Exception {Scanner sc = new Scanner(System.in);System.out.println("请输入用户名");String username = sc.nextLine();System.out.println("请输入密码");String password = sc.nextLine();Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection("jdbc:mysql:///java2303", "root", "123456");Statement statement = conn.createStatement();String sql = " select * from tb_user where username = '" + username + "' and password = '" + password +"'";System.out.println(sql);ResultSet rs = statement.executeQuery(sql);if(rs.next()){//登录成功System.out.println("登录成功");}else{//登录失败System.out.println("登录失败");}rs.close();statement.close();conn.close();}
}

4.3 登录案例分析-SQL注入问题

以上代码会出现SQL注入问题

  • 用户输入的数据中有 SQL 关键字或语法并且参与了 SQL 语句的编译,导致 SQL 语句编译后的条件含义为 true,一直得到正确的结果。这种现象称为 SQL 注入。
  • 字符串的拼接操作也是非常的不方便

4.4 登录案例更新

public class JDBCDemo06 {public static void main(String[] args) throws Exception {Scanner sc = new Scanner(System.in);System.out.println("请输入用户名");String username = sc.nextLine();System.out.println("请输入密码");String password = sc.nextLine();Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection("jdbc:mysql:///java2303", "root", "123456");//3、获取数据库操作对象PreparedStatement    预加载SQL语句PreparedStatement ps =conn.prepareStatement("select * from tb_user where username = ? and password = ?");//3.1 设置占位符的值/***  PreparedStatement对象中提供了一组方法*      setXXX(index从1开始,要传入的值)    XXX表示对应的java类型*/ps.setString(1,username);ps.setString(2,password);System.out.println(ps);//4、执行SQL语句ResultSet rs = ps.executeQuery();if(rs.next()){//登录成功System.out.println("登录成功");}else{//登录失败System.out.println("登录失败");}rs.close();ps.close();conn.close();}
}

4.5 PreparedStatement

PreparedStatement 继承了 Statement 接口,执行 SQL 语句的方法无异。

作用:

  • 预编译SQL 语句,效率高。
  • 安全,避免SQL注入

五、ORM映射

5.1 思想

ORM (Object Relational Mapping)

将数据库中的表的数据,一行一行的映射到Java对象中

ORM思想
请添加图片描述

5.2 实体类的规范

JavaBean设计规范
1、类名与表名一致,属性名和字段名一致

2、私有化属性对外提供set、get方法

3、提供有参和无参构造

4、基本数据类型要使用包装类(默认值)

5、在需要的时候实现序列化接口

5.3 代码实现

查询

public class JDBCDemo04 {public static void main(String[] args) throws Exception {//1、注册驱动Class.forName("com.mysql.jdbc.Driver");//2、获取数据库连接对象Connection conn = DriverManager.getConnection("jdbc:mysql:///java2303", "root", "123456");//3、获取数据库操作对象Statement statement = conn.createStatement();//4、执行SQL语句ResultSet rs = statement.executeQuery("select * from emp");//5、处理结果集//定义List集合保存所有的emp对象List<Emp> empList = new ArrayList<>();while(rs.next()){int empno = rs.getInt("empno");String ename = rs.getString("ename");String job = rs.getString("job");int mgr = rs.getInt("mgr");Date hiredate = rs.getDate("hiredate");double sal = rs.getDouble("sal");double comm = rs.getDouble("comm");int deptno = rs.getInt("deptno");//将查询的结果存放到Emp对象中Emp emp = new Emp(empno,ename,job,mgr,hiredate,sal,comm,deptno);//将Emp对象添加到List中empList.add(emp);}//遍历集合中所有元素empList.forEach(System.out::println);
//        for(Emp emp : empList){
//            System.out.println(emp);
//        }//6、释放资源rs.close();statement.close();conn.close();}
}

6 封装工具类

1、注册数据库驱动(静态代码块)

2、获取数据库连接 (方法:getConnection)

3、释放资源 (方法:closeAll(Connection , Statement , ResultSet ))

4、将配置信息放到properties配置文件中,减少硬编码

6.1 代码实现

工具类代码

/**
* 数据库工具类*/
public class JDBCUtils {/*** 1、注册驱动(只需要注册一次)*      可以将注册驱动的代码写到静态代码块中* 2、获取数据库连接*      提供静态一个方法,用于返回数据库连接对象* 3、关闭资源*      提供静态一个方法,用于释放资源* 4、硬编码问题(.xml  .properties)*      将数据源信息保存到配置文件中,然后在代码中进行读取*      properties文件的格式:key和value都是String类型*              key=value*/private static String driver;private static String url;private static String username;private static String password;static{try {//读取配置文件Properties properties = new Properties();//通过类对象读取当前类路径下的资源InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");//将配置文件中的信息读取到Properties集合中properties.load(in);//从集合中取出数据driver = properties.getProperty("driver123");url = properties.getProperty("url");username = properties.getProperty("username");password = properties.getProperty("password");//注册驱动Class.forName(driver);} catch (Exception e) {e.printStackTrace();}}public static Connection getConnection(){Connection conn = null;try {conn = DriverManager.getConnection(url,username,password);} catch (SQLException throwables) {throwables.printStackTrace();}return conn;}public static void closeAll(Connection conn, Statement statement, ResultSet rs){try {if(rs!=null)rs.close();if(statement != null)statement.close();if(conn != null)conn.close();} catch (SQLException throwables) {throwables.printStackTrace();}}
}

编写配置文件properties (集合工具类-自己补充)

  • 在src更目录下创建xx.properties的new file
  • 集合键值对 driver = com.mysql.jdbc.Driver url = username = password =
  • 在静态代码块读取配置文件
    1. 创建properties对象

配置文件 db.properties

driver123=com.mysql.jdbc.Driver
url=jdbc:mysql:///java2303
username=root
password=123456

6.2 工具类测试

public class JDBCDemo01 {public static void main(String[] args) throws SQLException {//2、获取数据库连接Connection conn = JDBCUtils.getConnection();//3、获取数据库操作对象PreparedStatement ps = conn.prepareStatement("select * from emp");//4、执行SQL语句ResultSet rs = ps.executeQuery();//5、处理结果集while(rs.next()){int empno = rs.getInt("empno");String ename = rs.getString("ename");String job = rs.getString("job");int mgr = rs.getInt("mgr");Date hiredate = rs.getDate("hiredate");double sal = rs.getDouble("sal");double comm = rs.getDouble("comm");int deptno = rs.getInt("deptno");System.out.println(ename);}//6、释放资源JDBCUtils.closeAll(conn,ps,rs);}
}

7 DAO (Data Access Object)

DAO 实现了业务逻辑与数据库访问相分离。

  • 对同一张表的所有操作封装在XxxDaoImpl对象中。
  • 根据增删改查的不同功能实现具体的方法(insert、update、delete、select、selectAll)。

7.1 开发流程

7.1.1 EmpDao接口

public interface EmpDao {//增加员工int insertEmp(Emp emp) throws SQLException;//删除员工int deleteEmp(int empno);//修改员工int updateEmp(Emp emp) throws SQLException;//查询所有员工List<Emp> selectAll() throws SQLException;//查询单个员工Emp selectOne(int empno);
}

7.1.2 实体类

com.qf.pojo包下创建实体类

public class Emp {private Integer empno;private String ename;private String job;private Integer mgr;private Date hiredate;private Double sal;private Double comm;private Integer deptno;//省略get、set、构造方法
}

7.1.3 EmpDao实现类

public class EmpDaoImpl implements EmpDao {@Overridepublic int insertEmp(Emp emp) throws SQLException {//2、获取数据库连接对象Connection conn = JDBCUtils.getConnection();//3、获取数据库操作对象PreparedStatement ps = conn.prepareStatement("insert into emp values(?,?,?,?,?,?,?,?)");//3.1设置占位符的值ps.setInt(1,emp.getEmpno());ps.setString(2,emp.getEname());ps.setString(3,emp.getJob());ps.setInt(4,emp.getMgr());//将util.date 转换成 sql.dateps.setDate(5,new Date(emp.getHireadate().getTime()));ps.setDouble(6,emp.getSal());ps.setDouble(7,emp.getComm());ps.setInt(8,emp.getDeptno());//4、执行SQL语句int count = ps.executeUpdate();//5、处理结果//6、释放资源JDBCUtils.closeAll(conn,ps,null);return count;}@Overridepublic int deleteEmp(int empno) {return 0;}@Overridepublic int updateEmp(Emp emp) throws SQLException {//2、获取数据库连接对象Connection conn = JDBCUtils.getConnection();//3、获取数据库操作对象PreparedStatement ps = conn.prepareStatement("update emp set ename=?,job=?,mgr=?,hiredate=?,sal=?,comm=?,deptno=? where empno = ?");//3.1设置占位符的值ps.setString(1,emp.getEname());ps.setString(2,emp.getJob());ps.setInt(3,emp.getMgr());//将util.date 转换成 sql.dateps.setDate(4,new Date(emp.getHireadate().getTime()));ps.setDouble(5,emp.getSal());ps.setDouble(6,emp.getComm());ps.setInt(7,emp.getDeptno());ps.setInt(8,emp.getEmpno());//4、执行SQL语句int count = ps.executeUpdate();//5、处理结果//6、释放资源JDBCUtils.closeAll(conn,ps,null);return count;}@Overridepublic List<Emp> selectAll() throws SQLException {//2、获取数据库连接对象Connection conn = JDBCUtils.getConnection();//3、获取数据库操作对象PreparedStatement ps = conn.prepareStatement("select * from emp");//4、执行SQL语句ResultSet rs = ps.executeQuery();//5、处理结果集List<Emp> empList = new ArrayList<>();while(rs.next()){int empno = rs.getInt("empno");String ename = rs.getString("ename");String job = rs.getString("job");int mgr = rs.getInt("mgr");Date hiredate = rs.getDate("hiredate");double sal = rs.getDouble("sal");double comm = rs.getDouble("comm");int deptno = rs.getInt("deptno");//将查询的结果存放到Emp对象中Emp emp = new Emp(empno,ename,job,mgr,hiredate,sal,comm,deptno);//将Emp对象添加到List中empList.add(emp);}//6、释放资源JDBCUtils.closeAll(conn,ps,rs);return empList;}@Overridepublic Emp selectOne(int empno) {return null;}
}

7.1.4 测试类

public class TestEmpDao {public static void main(String[] args) throws Exception {//测试查询所有
//        EmpDao empDao = new EmpDaoImpl();
//        List<Emp> empList = empDao.selectAll();
//        System.out.println(empList);//测试增加
//        EmpDao empDao = new EmpDaoImpl();
//        Emp emp = new Emp(9000,"韩梅梅","mysql",7369,new Date(),4000d,200d,30);
//        System.out.println(empDao.insertEmp(emp));//测试修改EmpDao empDao = new EmpDaoImpl();Emp emp = new Emp(9000,"李雷","java",7369,new Date(),40000d,200d,30);System.out.println(empDao.updateEmp(emp));}
}

8 Service 业务 【掌握】

8.1 什么是业务

代表用户完成的一个业务功能,可以由一个或多个DAO的调用组成。(软件所提供的一个功能都叫业务)

8.2 转账业务开发

转账业务分析
在这里插入图片描述
public class AccountServiceImpl implements AccountService {AccountDao accountDao = new AccountDaoImpl();@Overridepublic String zhuanZhang(String fromName, String password, String toName, double money) {try {//1、验证我方用户密码Account account = accountDao.selectAccount(fromName);if(account == null){return "用户名不存在";}if(!account.getPassword().equals(password)){return "用户密码不正确";}//2、验证余额if(account.getMoney() < money){return "用户余额不足";}//3、验证对方用户if(accountDao.selectAccount(toName) == null){return "对方用户名不存在";}//4、我方扣钱accountDao.updateAccount(fromName,-money);System.out.println(10/0);//5、对方加钱accountDao.updateAccount(toName,money);return "转账成功";} catch (SQLException throwables) {throwables.printStackTrace();}return "转账失败";}
}

9 事务

在JDBC 中,获得 Connection 对象开始事务–提交或回滚–关闭连接。其事务操作是

  • conn.setAutoCommit(false);//设置事务为手动提交
  • conn.commit();//手动提交事务
  • conn.rollback();//手动回滚事务

9.1 转账业务实现

public class AccountServiceImpl2 implements AccountService {AccountDao accountDao = new AccountDaoImpl();@Overridepublic String zhuanZhang(String fromName, String password, String toName, double money) {Connection conn = JDBCUtils.getConnection();try {           //1、验证我方用户密码Account account = accountDao.selectAccount(fromName);if(account == null){return "用户名不存在";}if(!account.getPassword().equals(password)){return "用户密码不正确";}//2、验证余额if(account.getMoney() < money){return "用户余额不足";}//3、验证对方用户if(accountDao.selectAccount(toName) == null){return "对方用户名不存在";}//4、我方扣钱accountDao.updateAccount(fromName,-money);//System.out.println(10/0);//5、对方加钱accountDao.updateAccount(toName,money);//提交事务conn.commit();return "转账成功";} catch (Exception throwables) {throwables.printStackTrace();try {//回滚事务conn.rollback();} catch (SQLException throwables) {throwables.printStackTrace();}}return "转账失败";}
}

注意:此时Service中的Connection与Dao中的Connection对象不一致,无法实现事务回滚

9.2 解决方案1:传递 Connection

  • 如果使用传递Connection,容易造成接口污染(BadSmell)。
  • 定义接口是为了更容易更换实现,而将 Connection定义在接口中,会造成污染当前接口。

9.3 解决方案2:ThreadLocal

  • 可以将整个线程中(单线程)中,存储一个共享值。
  • 线程拥有一个类似 Map 的属性,键值对结构<ThreadLocal对象,值>。

9.4 使用ThreadLocal更新JDBC工具类

/*** ThreadLocal<T>:能保存对象,能保证在同一个线程下获取到的对象是同一个*     set(T);*     get();*     remove();*/
static ThreadLocal<Connection> tl = new ThreadLocal<>();public static Connection getConnection(){//1、从ThreadLocal获取Connection//2、获取获取到了connection对象直接返回//3、创建Connection对象并存到ThreadLocal中,在进行返回Connection conn = tl.get();try {if(conn == null){conn = DriverManager.getConnection(url,username,password);tl.set(conn);}} catch (SQLException throwables) {throwables.printStackTrace();}return conn;
}

此时需要注意,如果关闭了Connetion连接,但是在ThreadLocal中还是保存着Connetion对象。下次会获取到一个已经关闭的Connection对象,所以需要从ThreadLocal中移除

9.5 事务封装

将事务的开启、提交、回滚都封装在工具类中,业务层调用即可。

 //封装事务操作的三个方法
public static void begin(){//1、获取Connection对象Connection conn = getConnection();try {//2、开启事务conn.setAutoCommit(false);} catch (SQLException throwables) {throwables.printStackTrace();}
}
public static void commit(){//1、获取Connection对象Connection conn = getConnection();try {//2、提交事务conn.commit();} catch (SQLException throwables) {throwables.printStackTrace();}finally {try {//3、关闭Connection资源conn.close();//从ThreadLocal中将connection移除掉tl.remove();} catch (SQLException throwables) {throwables.printStackTrace();}}
}
public static void rollback(){//1、获取Connection对象Connection conn = getConnection();try {//2、回滚事务conn.rollback();} catch (SQLException throwables) {throwables.printStackTrace();}finally {try {//3、关闭Connection资源conn.close();//从ThreadLocal中将connection移除掉tl.remove();} catch (SQLException throwables) {throwables.printStackTrace();}}
}

9.6 最终的转账业务

public class AccountServiceImpl2 implements AccountService {AccountDao accountDao = new AccountDaoImpl();@Overridepublic String zhuanZhang(String fromName, String password, String toName, double money) {try {//开启事务JDBCUtils.begin();//1、验证我方用户密码Account account = accountDao.selectAccount(fromName);if(account == null){return "用户名不存在";}if(!account.getPassword().equals(password)){return "用户密码不正确";}//2、验证余额if(account.getMoney() < money){return "用户余额不足";}//3、验证对方用户if(accountDao.selectAccount(toName) == null){return "对方用户名不存在";}//4、我方扣钱accountDao.updateAccount(fromName,-money);//System.out.println(10/0);//5、对方加钱accountDao.updateAccount(toName,money);//提交事务JDBCUtils.commit();return "转账成功";} catch (Exception throwables) {throwables.printStackTrace();//回滚事务JDBCUtils.rollback();}return "转账失败";}
}

10 三层架构【理解】

三层架构原理
在这里插入图片描述
三层架构下包结构
在这里插入图片描述

11 单元测试

11.1 单元测试

/*** 单元测试:对已经编写完成的类、模块、方法进行测试* 使用步骤:*  1、导入单元测试的两个jar包(与驱动包导入一致)*  2、编写方法进行测试* 常用的注解:*    @Test         单元测试的方法*    @Before       在单元测试方法之前执行*    @After        在单元测试方法之后执行*    @BeforeClass  在类加载之前执行*    @AfterClass   在类卸载之后执行** 单元测试需要注意的问题*    1、@BeforeClass测试的方法必须要加static修饰*    2、单元测试的方法不能有参数,不能有返回值*    3、不能再单元测试中写Scanner输入内容	*/
@BeforeClass
public static void testBeforeClass(){System.out.println("BeforeClass类加载的时候执行");
}@Before
public void testBefore(){System.out.println("Before在单元测试方法之前执行(自动执行)");
}@Test
public void test01(){System.out.println("单元测试");
}
@After
public void testAfter(){System.out.println("After在单元测试方法之后执行(自动执行)");
}
@AfterClass
public static void testAfterClass(){System.out.println("BeforeClass类卸载的时候执行");
}

执行结果

BeforeClass类加载的时候执行
Before在单元测试方法之前执行(自动执行)
单元测试
After在单元测试方法之后执行(自动执行)
BeforeClass类卸载的时候执行

11.2 实际应用

在实际开发过程中,我们需要对写好的DAO层代码、Service层代码进行测试

一般就是对DAO、Service层中的每一个方法进行测试

public class AccountTest {@Testpublic void testZhuanZhang(){AccountService accountService = new AccountServiceImpl2();String s = accountService.zhuanZhang("jack","123","rose",200);System.out.println(s);}
}

12 连接池【理解掌握】

12.1 Druid连接池

在程序初始化时,预先创建指定数量的数据库连接对象存储在池中。当需要连接数据库时,从连接池中取出现有连接;使用完毕后,也不会进行关闭,而是放回池中,实现复用,节省资源。

  • 创建 db.properties 配置文件。
  • 引入druid的jar 文件,添加到类路径

12.2 db.properties

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///java2303?useSSL=false
username=root
password=123456
#初始化连接   (初始化连接池的,里面默认就已经存在了20个Connection连接)
initialSize=20
#最大连接数量  (当初始的20个连接不够的时候,最大会创建到50个)
maxActive=50
#最小空闲连接  (当连接池中的连接,没有被使用,就会减少到5个)
minIdle=5
#超时等待时间  (当连接数超过最大连接数,会等待5秒,如果5秒后还没有空闲连接,就会抛出异常)
maxWait=5000

12.3 最终版JDBC工具类

DruidDataSourceFactory 导包com.alibaba.druid.pool

public class JDBCUtils {//定义数据库连接池private static DataSource dataSource;//初始化连接池对象static{try {Properties properties = new Properties();InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");properties.load(in);//初始化连接池对象dataSource = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}//返回连接池对象public static DataSource getDataSource(){return dataSource;}//使用ThreadLocal保证Connection在同一个线程下唯一static ThreadLocal<Connection> tl = new ThreadLocal<>();public static Connection getConnection(){Connection conn = tl.get();try {if(conn == null){conn = dataSource.getConnection();tl.set(conn);}} catch (SQLException throwables) {throwables.printStackTrace();}return conn;}public static void closeAll(Connection connection, Statement statement , ResultSet rs){try {if(rs!=null)rs.close();if(statement!=null)statement.close();if(connection!=null)connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}public static void begin(){Connection conn = getConnection();try {conn.setAutoCommit(false);} catch (SQLException throwables) {throwables.printStackTrace();}}public static void commit(){Connection conn = getConnection();try {conn.commit();} catch (SQLException throwables) {throwables.printStackTrace();}finally {try {conn.close();tl.remove();} catch (SQLException throwables) {throwables.printStackTrace();}}}public static void rollback(){Connection conn = getConnection();try {conn.rollback();} catch (SQLException throwables) {throwables.printStackTrace();}finally {try {conn.close();tl.remove();} catch (SQLException throwables) {throwables.printStackTrace();}}}
}

12.4 连接池测试

public class TestDruidDataSource {public static void main(String[] args) throws SQLException {
//        Connection conn1 = JDBCUtils.getConnection();
//        System.out.println(conn1);
//        Connection conn2 = JDBCUtils.getConnection();
//        System.out.println(conn2);for (int i = 0; i < 51; i++) {Connection connection = JDBCUtils.getDataSource().getConnection();System.out.println(connection);connection.close();//并不是关闭连接,而是归还到连接池中}}
}

14 DaoUtils工具类【理解】

将Dao层中增删改的代码进行封装

13.1 工具类实现

public class DaoUtils {//更新操作(增删改) insert into emp values(?,?,?,?,?,?,?,?)public static int commonsUpdate(String sql,Object... args) throws SQLException {//1、获取数据库连接对象Connection conn = JDBCUtils.getConnection();PreparedStatement ps = null;try {//2、获取数据库操作对象ps = conn.prepareStatement(sql);//3、设置占位符的值for (int i = 0; i < args.length; i++) {ps.setObject(i+1,args[i]);}//4、执行sql语句int count = ps.executeUpdate();//5、处理结果return count;} finally {//6、关闭资源JDBCUtils.closeAll(null,ps,null);}}public static <T> List<T> commonsQuery(String sql, Class c, Object... args) throws Exception {PreparedStatement ps = null;ResultSet rs = null;try {//1、获取数据库连接对象Connection conn = JDBCUtils.getConnection();//2、获取数据库操作对象ps = conn.prepareStatement(sql);//3、设置占位符的值for (int i = 0; i < args.length; i++) {ps.setObject(i+1,args[i]);}//4、执行SQL语句rs = ps.executeQuery();//5、处理结果集List<T> list = new ArrayList<>();while(rs.next()){//通过类对象获取类的属性Field[] fields = c.getDeclaredFields();T obj = (T) c.newInstance();for (int i = 0; i < fields.length; i++) {//暴力反射fields[i].setAccessible(true);fields[i].set(obj,rs.getObject(i+1));}//将对象装到List集合中list.add(obj);}return list;}finally {JDBCUtils.closeAll(null,ps,rs);}}
}

13.2 DaoUtils工具类使用

public class EmpDaoImpl implements EmpDao {@Overridepublic int insertEmp(Emp emp) throws SQLException {String sql = "insert into emp values(?,?,?,?,?,?,?,?)";Object[] args = {emp.getEmpno(),emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHireadate(),emp.getSal(),emp.getComm(),emp.getDeptno()};return DaoUtils.commonsUpdate(sql,args);}@Overridepublic int updateEmp(Emp emp) throws SQLException {String sql = "update emp set ename=?,job=?,mgr=?,hiredate=?,sal=?,comm=?,deptno=? where empno = ?";Object[] args = {emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHireadate(),emp.getSal(),emp.getComm(),emp.getDeptno(),emp.getEmpno()};return  DaoUtils.commonsUpdate(sql,args);}@Overridepublic int deleteEmp(int empno) throws SQLException {String sql = "delete from emp where empno = ?";Object[] args = {empno};return DaoUtils.commonsUpdate(sql,args);}@Overridepublic List<Emp> selectAll() throws Exception {String sql = "select * from emp";return DaoUtils.commonsQuery(sql,Emp.class);}
}

14 DBUtils工具类

14.1 DBUtils简介

DbUtils是Java编程中数据库操作实用小工具,小巧、简单、实用

  • 对于数据表的查询操作,可以把结果转换为List、Array、Set等集合。便于操作。
  • 对于数据表的DML操作,也变得很简单(只需要写SQL语句)。

14.2 DbUtils核心API

  • ResultSetHandler接口:转换类型接口
    • BeanHandler类:实现类,把一条记录转换成对象
    • BeanListHandler类:实现类,把多条记录转换成List集合。
    • ScalarHandler类:实现类,适合获取一行一列的数据。
    • MapHandler类: 实现类,把一条记录转换成Map集合
    • MapListHandler类:实现类,把多条记录转换成List集合。
  • QueryRunner:执行sql语句的类
    • 增、删、改:update();
    • 查询:query();

14.3 DbUtils的使用步骤

导入jar包

  • mysql连接驱动jar包
  • 导入druid 的jar包
  • database.properties配置文件
  • 导入commons-dbutils的jar包

14.4 DBUtils使用

使用DBUtils实现增删改查

public class EmpDaoImpl implements EmpDao {@Overridepublic int insertEmp(Emp emp) throws SQLException {//1、创建QueryRunner对象//如果是更新(增删改)操作,那么就用无参的构造QueryRunner qr = new QueryRunner();//2、通过QueryRunner对象调用updateString sql = "insert into emp values(?,?,?,?,?,?,?,?)";Object[] args = {emp.getEmpno(),emp.getEname1(),emp.getJob(),emp.getMgr(),emp.getHireadate(),emp.getSal(),emp.getComm(),emp.getDeptno()};return qr.update(JDBCUtils.getConnection(),sql,args);}@Overridepublic int updateEmp(Emp emp) throws SQLException {//1、创建QueryRunner对象//如果是更新(增删改)操作,那么就用无参的构造QueryRunner qr = new QueryRunner();//2、通过QueryRunner对象调用updateString sql = "update emp set ename=?,job=?,mgr=?,hiredate=?,sal=?,comm=?,deptno=? where empno = ?";Object[] args = {emp.getEname1(),emp.getJob(),emp.getMgr(),emp.getHireadate(),emp.getSal(),emp.getComm(),emp.getDeptno(),emp.getEmpno()};return qr.update(JDBCUtils.getConnection(),sql,args);}@Overridepublic int deleteEmp(int empno) throws SQLException {//1、创建QueryRunner对象//如果是更新(增删改)操作,那么就用无参的构造QueryRunner qr = new QueryRunner();//2、通过QueryRunner对象调用updateString sql = "delete from emp where empno = ?";Object[] args = {empno};return qr.update(JDBCUtils.getConnection(),sql,args);}@Overridepublic List<Emp> selectAll() throws Exception {//1、创建QueryRunner对象//如果是查询操作,那么就用有参的构造,传递连接池对象(使用完成之后QueryRunner会自动关闭(回收))QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());//2、通过QueryRunner对象调用queryString sql = "select empno,ename ename1,job,mgr,hiredate hireadate,sal,comm,deptno from emp";//如果是集合就创建BeanListHandler对象,如果是实体类就创建BeanHandler对象List<Emp> empList = qr.query(sql, new BeanListHandler<Emp>(Emp.class));return empList;}@Overridepublic Emp selectOne(int empno) throws SQLException {//1、创建QueryRunner对象//如果是查询操作,那么就用有参的构造,传递连接池对象(使用完成之后QueryRunner会自动关闭(回收))QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());//2、通过QueryRunner对象调用queryString sql = "select * from emp where empno = ?";Object[] args = {empno};Emp emp = qr.query(sql, new BeanHandler<Emp>(Emp.class),args);return emp;}@Overridepublic long count() throws SQLException {//1、创建QueryRunner对象//如果是查询操作,那么就用有参的构造,传递连接池对象(使用完成之后QueryRunner会自动关闭(回收))QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());String sql = "select count(*) from emp";Long count = qr.query(sql, new ScalarHandler<Long>());return count;}
}

14.5 字段与属性名不一致

如果数据库的字段名与实体类中的属性名不一致,则无法完成映射,值会显示null

2种解决:

  • 在查询语句中取别名

后期自定义映射

@Override
public List<Emp> selectAll() throws Exception {//1、创建QueryRunner对象//如果是查询操作,那么就用有参的构造,传递连接池对象(使用完成之后QueryRunner会自动关闭(回收))QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());//2、通过QueryRunner对象调用query//通过别名进行数据映射String sql = "select empno,ename ename1,job,mgr,hiredate hireadate,sal,comm,deptno from emp";//如果是集合就创建BeanListHandler对象,如果是实体类就创建BeanHandler对象List<Emp> empList = qr.query(sql, new BeanListHandler<Emp>(Emp.class));return empList;
}
public class Emp {private Integer empno;private String ename1; //这个与数据库字段不一致private String job;private Integer mgr;private Date hireadate; //这个与数据库字段不一致private Double sal;private Double comm;private Integer deptno;//省略set、get、构造方法
}

15 Lombok插件

Lombok简化编写类的构造方法、setget方法以及toString方法

使用步骤

安装插件,需要重启目前IDEA版本已经自带此插件无需安装
在这里插入图片描述
|
开启IEDA注解可用需要在setting中进行设置还需要在setting for newproject中设置
在这里插入图片描述
    |
新版本使用lombok插件需要添加配置需要在setting中进行设置还需要在setting for newproject中设置
-Djps.track.ap.dependencies=false
在这里插入图片描述
导入jar包
在这里插入图片描述
编写实体类
在这里插入图片描述

相关文章:

Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)

文章目录1 JDBC&#xff08;Java Database Connectivity&#xff09;1.1 什么是 JDBC&#xff1f;1.2 JDBC 核心思想2 JDBC开发步骤【重点】2.0 环境准备2.1 注册数据库驱动2.2 获取数据库的连接2.3 获取数据库操作对象Statement2.4 通过Statement对象执行SQL语句2.5 处理返回结…...

vue3生命周期

一、Vue3中的生命周期 1、setup() : 开始创建组件之前&#xff0c;在 beforeCreate 和 created 之前执行&#xff0c;创建的是 data 和 method 2、onBeforeMount() : 组件挂载到节点上之前执行的函数&#xff1b; 3、onMounted() : 组件挂载完成后执行的函数&#xff1b; 4、…...

Python学习笔记10:开箱即用

开箱即用 模块 python系统路径 import sys, pprint pprint.pprint(sys.path) [,D:\\Program Files\\Python\\Lib\\idlelib,D:\\Program Files\\Python\\python310.zip,D:\\Program Files\\Python\\DLLs,D:\\Program Files\\Python\\lib,D:\\Program Files\\Python,D:\\Progr…...

详解JAVA反射

目录 1.概述 2.获取Class对象 3.API 3.1.实例化对象 3.2.方法 3.3.属性 1.概述 反射&#xff0c;JAVA提供的一种在运行时获取类的信息并动态操作类的能力。JAVA反射允许我们在运行时获取类的属性、方法、构造函数等信息&#xff0c;并能够动态地操作它们。 2.获取Class…...

在nestjs中进行typeorm cli迁移(migration)的配置

在nestjs中进行typeorm cli迁移(migration)的配置 在学习nestjs过程中发现typeorm的迁移配置十分麻烦,似乎许多方法都是旧版本的配置&#xff0c;无法直接使用. 花了挺长时间总算解决了这个配置问题. db.config.ts 先创建db.config.ts, 该文件export了两个对象&#xff0c;其…...

前端工程构建问题汇总

1.less less-loader安装失败问题 npm install less-loader --save --legacy-peer-deps 加上–legacy-peer-deps就可以了 在NPM v7中&#xff0c;现在默认安装peerDependencies&#xff0c;这会导致版本冲突&#xff0c;从而中断安装过程。 –legacy-peer-deps标志是在v7中引…...

某马程序员NodeJS速学笔记

文章目录前言一、什么是Node.js?二、fs文件系统模块三、Http模块四、模块化五、开发属于自己的包模块加载机制六、Express1.初识ExpressGET/POSTnodemon2.路由模块化3.中间件中间件分类自定义中间件4. 跨域问题七、Mysql模块安装与配置基本使用Web开发模式Session认证JWT八、m…...

SpringMVC DispatcherServlet源码(6) 完结 静态资源原理

阅读源码&#xff0c;分析静态资源处理器相关组件&#xff1a; 使用SimpleUrlHandlerMapping管理url -> 处理器映射关系spring mvc使用WebMvcConfigurationSupport注入SimpleUrlHandlerMapping组件DelegatingWebMvcConfiguration可以使用WebMvcConfigurer的配置静态资源url…...

2023年全国最新会计专业技术资格精选真题及答案9

百分百题库提供会计专业技术资格考试试题、会计考试预测题、会计专业技术资格考试真题、会计证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 四、材料题 1.某企业为增值税一般纳税人&#xff0c;2019年12月初“应付职工薪酬…...

Web3中文|把Web3装进口袋,Solana手机Saga有何魔力?

2月23日&#xff0c;Solana Web3手机Saga发布新的消息&#xff0c;将推出NFT铸造应用程序Minty Fresh。在Minty Fresh&#xff0c;用户仅需轻点并完成拍摄&#xff0c;就可以直接在手机中进行NFT铸造&#xff0c;并在几秒钟内将其转换为链上NFT&#xff0c;NFT还可以发布在 Ins…...

【配电网优化】基于串行和并行ADMM算法的配电网优化研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

数据结构初阶 -- 顺序表

数据结构初阶 链表的讲解 目录 一. 线性表 1.1 定义 1.2 特点 二. 顺序表 2.1 定义 2.2 代码 2.3 功能需求 2.4 静态顺序表的特点以及缺点 2.5 动态的顺序表 2.6 动态顺序表接口的实现 三. 代码 头文件 主文件 一. 线性表 1.1 定义 线性表&#xff08;linear li…...

uniapp:3分钟搞定在线推送uni.createPushMessage,uni.onPushMessage

安卓端 在线推送功能演示&#xff1a; 1、dcloud后台申请开通uniPush dcloud后台 &#xff08;1&#xff09;&#xff1a;找到我的应用 &#xff08;2&#xff09;&#xff1a;点进去后&#xff0c;各平台信息&#xff0c;点击新增 &#xff08;3&#xff09;&#xff1a;填…...

C/C++开发,无可避免的多线程(篇一).跨平台并行编程姗姗来迟

一、编译环境准备 在正式进入c/c多线程编程系列之前&#xff0c;先来搭建支持多线程编译的编译环境。 1.1 MinGW&#xff08;win&#xff09; 进入Downloads - MinGW-w64下载页面&#xff0c;选择MinGW-w64-builds跳转下载&#xff0c; 再次进行跳转&#xff1a; 然后进入下载页…...

如何把照片的底色修改为想要的颜色

如何给照片更换底色&#xff1f;其实有可以一键给照片更换底色的 APP &#xff0c;但是几乎都要收费。如果想要免费的给照片更换底色的话&#xff0c;分享两种简单便捷的方法给你。掌握了这项技能&#xff0c;以后就不用店花钱处理啦&#xff01;1、免费&#xff01;线上快速 给…...

【高效办公】批量生成固定模板的文件夹名称

老师让你按照他的要求生成每位学生的文件夹,你是学委,让你马上完成该任务,但你又不想是手动一个一个码字,因此聪明的你就看到了本篇文章啦!!! 虽说一个人懒惰,并不是好的事情。 但这个似乎合情合理啊~ 然后,就动手想办法,一开始就真的打算码字了。。 思路 在实际开…...

redis的集群方式

1.主从复制 主从复制原理&#xff1a; 从服务器连接主服务器&#xff0c;发送SYNC命令&#xff1b; 主服务器接收到SYNC命名后&#xff0c;开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令&#xff1b; 主服务器BGSAVE执行完后&#xff0c;向所有从服务…...

温控负荷的需求响应潜力评估及其协同优化管理研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

模电学习9. MOS管使用入门

模电学习9. MOS管使用入门一、mos管理简介1. 简介2. mos管理的特点3. MOS管的工作状态&#xff08;1&#xff09;放大功能&#xff08;2&#xff09;截止区&#xff08;3&#xff09;饱和区3. Mos管的分类&#xff08;1&#xff09;按照工作模式分类&#xff1a;&#xff08;2&…...

【算法】【数组与矩阵模块】正数组中累加和为给定值的最长子数组长度,空间复杂度O(1)解法

目录前言问题介绍解决方案代码编写java语言版本c语言版本c语言版本思考感悟写在最后前言 当前所有算法都使用测试用例运行过&#xff0c;但是不保证100%的测试用例&#xff0c;如果存在问题务必联系批评指正~ 在此感谢左大神让我对算法有了新的感悟认识&#xff01; 问题介绍 …...

3.1.2 创建表

文章目录1.创建表2.表创建基础3.表的主键4.使用null值5.使用AUTO_INCREMENT6.指定默认值7. 字段备注8.引擎类型9.外键1.创建表 表的创建一般有俩种方式&#xff0c;一种是使用交互式创建和管理表的工具&#xff0c;比如我们安装的MariaDB&#xff0c;另一种是使用MySQL 语句进…...

使用netlify实现自动化部署前端项目(无服务器版本)

介绍 本文以 github仓库进行介绍关联netlify的无服务前端自动化部署。用途&#xff1a;个人网站设计、小游戏等当然这只是让你入门~具体细节等待你自己去探索 实现 打开官方网站 如果没有注册过的账户&#xff0c;你需要使用 github 去进行登录。注册完成后会自动给你提示填…...

MATLAB点云数据处理(二十九):可视化点云之pcshow参数详解与快捷键操作

文章目录 1 pcshow简述2 最简单的pcshow3 带参数的pcshow3.1 点大小参数----MakerSize3.2 背景色参数----Background3.3 指定竖直轴参数----VerticalAxis3.4 指定垂直轴方向参数----VerticalAxisDir3.5 投影参数----Projection3.6 指定可视化平面参数----ViewPlane3.7 颜色渲染…...

顺序表——重置版

本期我们来实现数据结构的顺序表&#xff08;这个之前写过一次&#xff0c;不过本期和之前可能会略有不同&#xff0c;但大体相同&#xff09;&#xff0c;大家可以看一下我们之前完成的顺序表 (6条消息) 顺序表及其多种接口的实现_顺序表类中实现接口方法_KLZUQ的博客-CSDN博客…...

PyQt5自然语言处理入门案例笔记

前言 最近想将自然语言处理的项目进行可视化&#xff0c;尽量还是使用回Python语言&#xff0c;因此打算用PyQt来实现相应的功能。 入门案例 一个简单的自然语言处理的demo&#xff0c;使用PyQt框架&#xff0c;该demo可以读取文本文件&#xff0c;对文件中的文本进行情感分…...

使用 CSS 替换表行颜色?

跳到主内容 我正在使用一个带有交替行颜色的表格。 tr.d0 td {background-color: #CC9999;color: black; } tr.d1 td {background-color: #9999CC;color: black; }<table><tr class"d0"><td>One</td><td>one</td></tr>&…...

智能家居控制系统

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【项目经验】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站…...

Linux 进程:fork()与vfork()的对比

目录一、fork函数二、vfork函数1.函数的原理2.函数的隐患3.解决函数隐患的方法在Linux的进程学习中&#xff0c;常使用fork函数来创建子进程&#xff0c;但其实还有一个vfork函数也可以创建子进程。但是这两个函数的实现机制不同&#xff0c;fork函数使用了写实拷贝技术&#x…...

环境搭建02-Ubuntu16.04 安装CUDA和CUDNN、CUDA多版本替换

1、CUDA安装 &#xff08;1&#xff09;下载需要的CUDA版本 https://developer.nvidia.com/cuda-toolkit-archive &#xff08;2&#xff09;安装 sudo sh cuda_8.0.61_375.26_linux.run&#xff08;3&#xff09;添加环境 gedit ~/.bashrc在文件末尾添加&#xff1a; ex…...

HOT100--(3)无重复字符的最长子串

点击查看题目详情 大思路&#xff1a; 创建哈希表&#xff0c;元素类型为<char, int>&#xff0c;分别是字符与其对应下标 用哈希表来存储未重复的子串&#xff0c;若有重复则记录下当前子串最大值maxhashsize 并且开始以相同方法记录下一子串 遍历完成以后&#xff0c…...

wordpress 乱码/推广软文300字范文

硬件系统设计硬件平台基于ARM920T的处理器AT91RM9200&#xff0c;该处理器不仅有丰富的片上资源和标准接口&#xff0c;而且有低功耗、低成本、高性能、支持多种主要的嵌入式操作系统等特点&#xff0c;其采用5级整数流水线结构&#xff0c;性能高达200此方案的硬件系统结构设计…...

网站建设价格专注制作网站设计/互联网舆情

keras实现多种分类网络的方式更多python视频教程请到菜鸟教程https://www.piaodoo.com/Keras应该是最简单的一种深度学习框架了&#xff0c;入门非常的简单. 简单记录一下keras实现多种分类网络&#xff1a;如AlexNet、Vgg、ResNet 采用kaggle猫狗大战的数据作为数据集. 由于…...

电子商务网站建设感想/专业seo推广

在C语言中&#xff0c;结构是一种复合数据类型&#xff0c;其构成元素既可以是基本数据类型&#xff08;如int、long、float等&#xff09;的变量&#xff0c;也可以是一些复合数据类型&#xff08;如数组、结构、联合等&#xff09;的数据单元。在结构中&#xff0c;编译器为结…...

做网站的主要作用/网站建设的基本流程

皮尔逊Pearson 相关系数&#xff1a;使用前提&#xff1a;大小一致、连续、服从正态分布的数据集&#xff1b;斯皮尔曼spearman等级相关系数&#xff1a;皮尔逊Pearson 相关系数使用前提任何一个条件不满足时可以考虑使用该系数&#xff1b;肯德尔等级kendallta相关系数&#x…...

python做网站多少钱/seo搜索优化网站推广排名

爱生气的书店老板 当窗口移动时&#xff0c;只需关心移进窗口的和移出窗口的两个值即可。 class Solution { public:int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int X) {int ans 0,n customers.size(),cnt 0,res 0;for(int i0;i…...

做视频网站需要多大带宽/成都seo排名

https://chart.googleapis.com/chart?chtqr&chs150x150&choeUTF-8&chldL|4&chl%E8%BF%99%E9%87%8C%E6%89%93%E6%96%87%E5%AD%97 chl为需要生成的文字转载于:https://www.cnblogs.com/sxmny/archive/2012/11/18/2776383.html...