[{"content":"日志 idea创建一个空的Maven项目后运行编译报错：java: 不再支持源选项 7。请使用 8 或更高版本。 解决方法：\n方法1. 2.修改pom.xml文件如下： 确保确保 Maven 项目使用 Java 21 版本进行编译（设置为你自己的Java版本），并且源代码的字符编码为 UTF-8。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 \u0026lt;properties\u0026gt; \u0026lt;maven.compiler.source\u0026gt;21\u0026lt;/maven.compiler.source\u0026gt; \u0026lt;maven.compiler.target\u0026gt;21\u0026lt;/maven.compiler.target\u0026gt; \u0026lt;project.build.sourceEncoding\u0026gt;UTF-8\u0026lt;/project.build.sourceEncoding\u0026gt; \u0026lt;/properties\u0026gt; \u0026lt;build\u0026gt; \u0026lt;plugins\u0026gt; \u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;org.apache.maven.plugins\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;maven-compiler-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;3.8.1\u0026lt;/version\u0026gt; \u0026lt;!-- 使用最新版本 --\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;source\u0026gt;21\u0026lt;/source\u0026gt; \u0026lt;!-- 设置源代码版本为 Java 21 --\u0026gt; \u0026lt;target\u0026gt;21\u0026lt;/target\u0026gt; \u0026lt;!-- 设置目标平台版本为 Java 21 --\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/plugin\u0026gt; \u0026lt;/plugins\u0026gt; \u0026lt;/build\u0026gt; 最后重启下应该就好了。\n","date":"2025-11-18T07:57:45+08:00","image":"https://lingyicode.github.io/post/ssm%E6%97%A5%E5%BF%97/preview_hu_8515786ac5931cde.jpg","permalink":"https://lingyicode.github.io/post/ssm%E6%97%A5%E5%BF%97/","title":"SSM日志"},{"content":"第一个IOC案例 注：第一个IOC案例是Maven项目，项目结构如下：\n1.导入spring-context坐标 在pom.xml里的dependencies标签里面导入spring-context坐标：\n1 2 3 4 5 \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;org.springframework\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-context\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;6.2.12\u0026lt;/version\u0026gt; \u0026lt;/dependency\u0026gt; 2.配置Bean 先在resource文件夹里面创建applicationContext.xml,然后在beans标签中配置Bean：\n1 2 \u0026lt;bean id=\u0026#34;bookDao\u0026#34; class=\u0026#34;org.凌奕.dao.impl.BookDaoImpl\u0026#34;/\u0026gt; \u0026lt;bean id=\u0026#34;bookService\u0026#34; class=\u0026#34;org.凌奕.service.impl.BookServiceImpl\u0026#34;/\u0026gt; bean标签表示配置bean\nid表示给bean起名字\nclass表示给bean定义类型\n3.获取IOC容器 1 ApplicationContext ctx=new ClassPathApplicationContext(\u0026#34;applicationContext.xml\u0026#34;); 4.获取bean 1 2 BookDao bookDao=(BookDao)ctx.getBean(\u0026#34;bookDao\u0026#34;);//引号里面填的要和applicationContext.xml里面的id相对应。 bookDao.save(); ","date":"2025-11-17T23:49:45+08:00","image":"https://lingyicode.github.io/post/%E7%AC%AC%E4%B8%80%E4%B8%AAioc/preview_hu_74eda227c8bb7365.jpg","permalink":"https://lingyicode.github.io/post/%E7%AC%AC%E4%B8%80%E4%B8%AAioc/","title":"第一个IOC"},{"content":"第一个DI 1.基于IOC管理Bean\n2.Service中使用new创建的对象不能保留。\n3.Service中提供Dao的方法\n4.在applictioncontext.xml配置service和dao之间关系\n","date":"2025-11-17T23:47:45+08:00","image":"https://lingyicode.github.io/post/%E7%AC%AC%E4%B8%80%E4%B8%AAdi/preview_hu_648e3a4cc9f3f1de.jpg","permalink":"https://lingyicode.github.io/post/%E7%AC%AC%E4%B8%80%E4%B8%AAdi/","title":"第一个DI"},{"content":"艺术与篮球-19937 题目： 小蓝出生于一个艺术与运动并重的家庭中。\n妈妈是位书法家，她希望小蓝能通过练习书法，继承她的艺术天赋，并练就一手好字。爸爸是一名篮球教练，他希望小蓝能通过篮球锻炼身体，培养运动的激情和团队合作的精神。\n为了既满足妈妈的期望，又不辜负爸爸的心意，小蓝决定根据日期的笔画数来安排自己的练习。首先，他会将当天的日期按照“YYYYMMDD”的格式转换成一个8位数，然后将这8位数对应到汉字上，计算这些汉字的总笔画数。如果总笔画数超过50，他就去练习篮球；如果总笔画数不超过50，他就去练习书法。\n例如，在2024年1月1日这天，日期可表示为一个8位数字20240101，其转换为汉字是\u0026quot;二零二四零一零一”。日期的总笔画数为2+13+2+5+13+1+13+1=50，因此在这天，小蓝会去练习书法。\n一下是汉字的笔画数对照表：\n汉字 笔画数 零 13 一 1 二 2 三 3 四 5 五 4 六 4 七 2 八 2 九 2 现在，请你帮助小蓝统计一下，在2000年1月1日到2024年4月13日这段时间内，小蓝有多少天是在练习篮球？\n解题思路： 这道题目主要意思是从2000年1月1日~2024年4月13日期间，把年月日转换成汉字后总笔画数\u0026gt;50就去练篮球。求共有多少个满足条件的日期。 思路： 涉及到日期题目就要联想到数组、遍历、润平年\u0026hellip; 要定义一个值为每个月具体天数的数组； 题目中要把日期转换成汉字的话，那肯定要定义一个值为笔画数的汉字数组。 定义一个方法判断闰平年\u0026ndash;\u0026gt;{闰年：(year%400==0)||(year %4==0\u0026amp;\u0026amp;year%100!=0)} 定义两个变量，用于给汉字日期相加和满足条件的日期++。 三层循环(分别表示年月日)，再在循环里定义8个变量(用于取日期上每一个数字)。 然后就是在if判断转换后的汉字日期总笔画数是否\u0026gt;50，满足就++ 最后就是加一个判断条件:当日期满足2024-4-13就输出并且return;\n最后的if判断语句的结束语句为什么不用break;而是用return;？\n因为break是结束当前循环(day的循环)，return是终止当前方法的执行。它是终止solve()整个方法.\n最终代码： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public class Main { // 定义天数 static int months[] = {-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 定义数字对应的笔画数 static int hz[] = {13, 1, 2, 3, 5, 4, 4, 2, 2, 2}; // 判断闰平年 static boolean leaq(int year) { return (year % 400 == 0) || (year%4 == 0 \u0026amp;\u0026amp; year % 100 != 0); } static void solve() { int sum = 0, cnt = 0; for (int year = 2000; year \u0026lt;= 2024; year++) { if (leaq(year)) { months[2] = 29; } else { months[2] = 28; } for (int month = 1; month \u0026lt;= 12; month++) { for (int day = 1; day \u0026lt;= months[month]; day++) { int year_one, year_two, year_three, year_four; int month_one, month_two; int day_one, day_two; year_one = year / 1000; year_two = year / 100 % 10; year_three = year / 10 % 10; year_four = year % 10; month_one = month / 10; month_two = month % 10; day_one = day / 10; day_two = day % 10; sum = hz[year_one] + hz[year_two] + hz[year_three] + hz[year_four] + hz[month_one] + hz[month_two] + hz[day_one] + hz[day_two]; if (sum \u0026gt; 50) { cnt++; } if (year == 2024 \u0026amp;\u0026amp; month == 4 \u0026amp;\u0026amp; day == 13) { System.out.println(cnt); return; } } } } } public static void main(String[] args) { solve(); } } 也可以不用写solve()方法，直接在main写也行。\n","date":"2025-09-01T23:00:26+08:00","image":"https://lingyicode.github.io/post/%E8%89%BA%E6%9C%AF%E4%B8%8E%E7%AF%AE%E7%90%83-%E8%93%9D%E6%A1%A5%E6%9D%AF/preview_hu_3ae368d860668373.jpg","permalink":"https://lingyicode.github.io/post/%E8%89%BA%E6%9C%AF%E4%B8%8E%E7%AF%AE%E7%90%83-%E8%93%9D%E6%A1%A5%E6%9D%AF/","title":"艺术与篮球-蓝桥杯"},{"content":"区间次方和 - 3382 题目： 给定一个长度为n的整数数组α以及m个查询。每个查询包含三个整数l,r,k表示询问l～r之间所有元素的k次方和。请对每个查询输出一个答案，答案对 109 + 7 取 模。\n输入格式： 第一行输入两个整数n,m其含义如上述。\n第二行输入n个整数a[1],a[2],\u0026hellip;.,a[n]。\n接下来m行，每行输入三个整数l,r,k表示一个查询。\n输出格式： 输出m行，每行一个整数，表示查询的答案对109 + 7取模的结果。\n样例输入： 1 2 3 4 5 5 3 1 2 3 4 5 1 3 2 2 4 3 3 5 1 样例输出： 1 2 3 14 99 12 数据规模： 最终代码： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); long mod = 1000000007; int a[] = new int[n + 1]; long s[][] = new long[6][n + 1]; for (int i = 1; i \u0026lt;= n; i++) { a[i] = sc.nextInt(); } for (int i = 1; i \u0026lt;= n; i++) { int cur = 1; for (int k = 1; k \u0026lt;= 5; k++) { cur = (int) (cur * a[i] % mod); s[k][i] = (s[k][i - 1] + cur) % mod; } } for (int i = 1; i \u0026lt;= m; i++) { int l = sc.nextInt(); int r = sc.nextInt(); int k = sc.nextInt(); long result = s[k][r] - s[k][l - 1]; System.out.println(result); } } } ","date":"2025-08-30T18:09:50+08:00","image":"https://lingyicode.github.io/post/%E5%8C%BA%E9%97%B4%E6%AC%A1%E6%96%B9%E5%92%8C-%E8%93%9D%E6%A1%A5%E6%9D%AF/preview_hu_19f179816101a8ea.jpg","permalink":"https://lingyicode.github.io/post/%E5%8C%BA%E9%97%B4%E6%AC%A1%E6%96%B9%E5%92%8C-%E8%93%9D%E6%A1%A5%E6%9D%AF/","title":"区间次方和-蓝桥杯"},{"content":"弹珠堆放 - 17142 题目： 小蓝有 20230610 颗磁力弹珠，他对金字塔形状尤其感兴趣，如图:\n高度为 1 的金字塔需要 1 颗弹珠 高度为 2 的金字塔需要 4 颗弹珠 高度为 3 的金字塔需要 10 颗弹珠 高度为 4 的金字塔需要 20 颗弹珠 小兰想知道用他手里的弹珠可以摆出的最高金字塔高度是多少？\n解题思路： 这个题目大概就是给定一个序列经过公式计算求最大值。如果觉得题目给的数字太大了可以把总数量缩小为 20 个，就是题目上说的 4 层总数为 20。首先要把已知条件列出来：\n第 1 层：1\n第 2 层：4\n第 3 层：10\n第 4 层：20\n所以序列是 [1, 4, 10, 20]，如果觉得看这个序列没头绪那就把前面的层数加进来看有无规律。\n规律：第一层是 1 个弹珠，第二层总数为 4 个，那么第二层就是要 3 个，可以写出来：\n第一层 : 1\n第二层 : 3\n那题目给的 4 就是 1+3 得来的，那么这两层之间的规律可以看出第一层需要弹珠的数量 (1) + 第二层的层数 (2) 就是第两层需要的弹珠数量。\n那么一个简单的公式：第 n 层需要的弹珠数量 + 第 n+1 的层数 = 第 n 层需要的弹珠数量。\n所以就得出要定义两个变量（高度和当前层的弹珠数量）一个常量（总数量）：\n规律如图：\n金字塔高度 总弹珠数 各层珠分布 1 1 1 2 4 1 + 3 3 10 1 + 3 + 6 4 20 1 + 3 + 6 + 10 1 int sum = 20; int high = 1; int cnt = 1; ”定义完变量和常亮后就要进行循环了，但是我们不知道循环多少次，也不知道什么时候结束，有一个口诀：``知道次数用 for，否则用 while，所以就要用 while`\n进入 while 循环后要先把当前层的弹珠减去，所以就是 sum -= cnt;\n1 2 3 while (true) { sum -= cnt; } 然后再把 high++，因为层级增加嘛，加完高度后就要想那个公式怎么用了，我们可以带入一个值，按照定义的初始值带进去就编程 sum -= 1 --\u0026gt; 19, high++ --\u0026gt; 2，现在下一个层级有了，上一层需要的弹珠数量有了，两者相加即可：cnt += high; 可以带入值 1（第一层需要的弹珠数量）和 2（第二层），1+2=3 是第二层需要的弹珠数量。\n1 2 3 4 5 while (true) { sum -= cnt; high++; cnt += high; } 现在都求完后就要输出了，但是输出不可能直接输出，如果直接在循环外写输出，那循环就压根不会到循环外的输出语句，\n1 2 3 4 5 6 7 8 // 错误示例 while (true) { sum -= cnt; high++; cnt += high; } // 写在循环外压根执行不到这里，并且循环式死循环，因为没有停止条件。 System.out.println(high); 如果写循环里面可以输出，无论写在哪里都会报错，因为判断条件永远为真，最后会死循环一直执行\n1 2 3 4 5 6 7 8 9 // 错误示例 while (true) { sum -= cnt; // 或者放这：System.out.println(high); high++; // 再或者放这：System.out.println(high); cnt += high; System.out.println(high); } 所以还要给输出添加前置判断条件：假如总数量 = 0 的时候输出 high，但是这时候问题又出现了：假如最后 sum - cnt 成负数了就不输出了吗？显然不可能，我们还要再加一个判断条件：当 sum \u0026lt; 0 的时候 high 就要 -1。\n1 2 3 4 5 6 7 8 9 10 11 12 // 错误示例 while (true) { sum -= cnt; // 为什么在这里判断？因为上面是执行完事剩余的数量，如果都不成立那就继续执行下面的两句代码。 if (sum \u0026lt; 0) { System.out.println(high - 1); } else if (sum == 0) { System.out.println(high); } high++; cnt += high; } 如果你觉得写到这里就 结束 了那就错了，如果写到这里可以运行试下：显然结果是死循环。\n因为他会一直执行 high++; 和 cnt += high;，所以我们还要给每一个判断加上 break; 结束语句，这样才算真正完成。\n1 2 3 4 5 6 7 8 9 10 11 12 13 int sum = 20; int high = 1; int cnt = 1; while (true) { sum -= cnt; if (high \u0026lt; 0) { System.out.println(high - 1); break; } else if (high == 0) { System.out.println(high); break; } high++; cnt += high; } 把这个程序写出来后那最后把 sum 的值改成题目要求的 20230610 就行了。\n最终代码： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int sum = 20230610; int high = 1; int cnt = 1; while (true) { sum -= cnt; if (sum \u0026lt; 0) { System.out.println(high - 1); } else if (sum == 0) { System.out.println(high); } high++; cnt += high; } } } ","date":"2025-08-28T21:49:22+08:00","image":"https://lingyicode.github.io/post/%E5%BC%B9%E7%8F%A0%E5%A0%86%E6%94%BE-%E8%93%9D%E6%A1%A5%E6%9D%AF/preview_hu_422a9167177da49a.jpg","permalink":"https://lingyicode.github.io/post/%E5%BC%B9%E7%8F%A0%E5%A0%86%E6%94%BE-%E8%93%9D%E6%A1%A5%E6%9D%AF/","title":"弹珠堆放-蓝桥杯"},{"content":"JDBC-进阶 1.实体类与ORM 在使用JDBC操作数据库时，会发现数据库里面的数据是零散的，明明在数据库中是一行完整的数据，到了java中变成了一个一个的变量，不利于维护和管理，而java是面向对象的，一个表对应一个类，一行数据对应java中一个对象，一个列对应的是对象的属性，所以要把数据存储在一个载体里，这个载体是实体类。\nORM(Object Relational Mapping)思想，对象到关系数据库的映射，作用是在编程中，把面向对象的概念跟数据库中表的概念对应起来，以面向对象的角度操作数据库中的数据，即一张表对应一个类，一行数据对应一个对象，一个列对应一个属性\nJDBC的过程称为手动ORM。\n1 2 3 4 5 6 7 8 9 10 11 package com.凌奕.advanced.pojo; //类名对应的是数据库t_后面的单词全写。 public class Employee { private int empId; private String empName; private double empSalary; private Integer empAge; //此处写get、set、无参、有参、toString方法 } 封装代码：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package com.凌奕.advanced; import com.凌奕.advanced.pojo.Employee; import org.junit.Test; import java.sql.*; import java.util.ArrayList; import java.util.List; public class JDBCAdvanced { @Test public void testORM() throws Exception { //passowrd修改为mysql设置的密码 Connection connection = DriverManager.getConnection(\u0026#34;jdbc:mysql:///jdbcdemo\u0026#34;, \u0026#34;root\u0026#34;, \u0026#34;password\u0026#34;); PreparedStatement preparedStatement = connection.prepareStatement(\u0026#34;select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_id=?\u0026#34;); //给占位符赋值然后执行sql语句并返回结果。 preparedStatement.setInt(1, 4); ResultSet resultSet = preparedStatement.executeQuery(); Employee employee = null; while (resultSet.next()) { employee = new Employee(); int empId = resultSet.getInt(\u0026#34;emp_id\u0026#34;); String empName = resultSet.getString(\u0026#34;emp_name\u0026#34;); double empSalary = resultSet.getDouble(\u0026#34;emp_salary\u0026#34;); int empAge = resultSet.getInt(\u0026#34;emp_age\u0026#34;); employee.setEmpId(empId); employee.setEmpName(empName); employee.setEmpSalary(empSalary); employee.setEmpAge(empAge); } System.out.println(employee); resultSet.close(); preparedStatement.close(); connection.close(); } } 输出多个结果：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package com.凌奕.advanced; import com.凌奕.advanced.pojo.Employee; import org.junit.Test; import java.sql.*; import java.util.ArrayList; import java.util.List; public class JDBCAdvanced { @Test public void testORm() throws Exception { //passowrd修改为mysql设置的密码 Connection connection = DriverManager.getConnection(\u0026#34;jdbc:mysql:///jdbcdemo\u0026#34;, \u0026#34;root\u0026#34;, \u0026#34;password\u0026#34;); PreparedStatement preparedStatement = connection.prepareStatement(\u0026#34;select emp_id,emp_name,emp_salary,emp_age from t_emp\u0026#34;); ResultSet resultSet = preparedStatement.executeQuery(); Employee employee = null; List\u0026lt;Employee\u0026gt; employeeList = new ArrayList\u0026lt;\u0026gt;(); while (resultSet.next()) { employee =new Employee(); int empId = resultSet.getInt(\u0026#34;emp_id\u0026#34;); String empName = resultSet.getString(\u0026#34;emp_name\u0026#34;); double empSalary = resultSet.getDouble(\u0026#34;emp_salary\u0026#34;); int empAge = resultSet.getInt(\u0026#34;emp_age\u0026#34;); employee.setEmpId(empId); employee.setEmpName(empName); employee.setEmpSalary(empSalary); employee.setEmpAge(empAge); // 将每次循环封装的一个数据的对象存储在集合里 employeeList.add(employee); } for (Employee emp : employeeList) { System.out.println(emp); } resultSet.close(); preparedStatement.close(); connection.close(); } } ","date":"2025-08-25T15:29:50+08:00","image":"https://lingyicode.github.io/post/jdbc%E8%BF%9B%E9%98%B6/preview_hu_75ff29cdc741c020.jpg","permalink":"https://lingyicode.github.io/post/jdbc%E8%BF%9B%E9%98%B6/","title":"JDBC进阶"},{"content":"JDBC常见问题 资源的管理 在使用jdbc的相关资源时，比如Connection、PreparedStatement、ResultSet，使用完毕后，要及时关闭这些资源以释放数据库服务器资源和避免内存泄露等问题。\nSQL问题 SQL语句问题： java.sql.SQLSyntaxErrorException java.sql.SQLSyntaxErrorException：SQL语句错误异常，一般有几种可能：\n1.SQL语句错误，检查SQL语句，建议SQL语句在SQL工具(navicat、dataGrip)中测试后再赋值到java程序中。\n2.连接数据库的URL中，数据库名称编写错误，也会报该异常。\nSQL语句未设置参数问题 java.sql.SQLException: No value specified for parameter 1 在用预编译SQL语句时，如果有?占位符，要为每一个占位符赋值，否则报该错误。\n用户名或密码错误 在连接数据库时，如果用户名或密码输入错误，也会报SQLException，容易混淆，看清异常后面原因描述\n通信异常 com.mysql.cj.jdbc.exceptions.CommunicationsException:Communications link failure\n在连接数据库URL时，如果IP端口或端口写错了，会报以上异常\n","date":"2025-08-25T14:25:45+08:00","image":"https://lingyicode.github.io/post/jdbc%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%8F%8A%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E8%AF%A6%E8%A7%A3/preview_hu_a61d455a3f29fec4.jpg","permalink":"https://lingyicode.github.io/post/jdbc%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%8F%8A%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E8%AF%A6%E8%A7%A3/","title":"JDBC常见问题及异常处理详解"},{"content":"JDBC-入门 一、JDBC搭建： 1.准备数据库\n2.下载连接驱动jar包。\n3.创建Java项目，在项目下创建lib文件夹内，将下载完成的jar包复制到文件夹里面。\n4.选中lib文件夹右键\u0026ndash;\u0026gt;Add as Library(添加为库)，与项目集成。\n5.编写代码\n完整代码：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package com.凌奕.base; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class JDBCQuick { public static \u0026lt;connection\u0026gt; void main(String[] args) throws Exception { // 1.注册驱动 Class.forName(\u0026#34;com.mysql.cj.jdbc.Driver\u0026#34;); // 2.获取连接对象 String url = \u0026#34;jdbc:mysql://localhost:3306/jdbcdemo\u0026#34;; String username = \u0026#34;root\u0026#34;; //password修改成自己设置的mysql密码 String password = \u0026#34;password\u0026#34;; Connection connection = DriverManager.getConnection(url, username, password); // 3.获取执行sql语句的对象 --\u0026gt;把sql语句发送给mysql的对象 Statement statement = connection.createStatement(); // 4.编写SQL语句，并执行,接受返回的结果集 String sql = \u0026#34;select emp_id,emp_name,emp_salary,emp_age from t_emp;\u0026#34;; ResultSet resultSet = statement.executeQuery(sql); // 5.处理结果，遍历result结果集 while (resultSet.next()) { int empId = resultSet.getInt(\u0026#34;emp_id\u0026#34;); String empName = resultSet.getString(\u0026#34;emp_name\u0026#34;); double empSalary = resultSet.getDouble(\u0026#34;emp_salary\u0026#34;); int empAge = resultSet.getInt(\u0026#34;emp_age\u0026#34;); System.out.println(empId + \u0026#34;\\t\u0026#34; + empName + \u0026#34;\\t\u0026#34; + empSalary + \u0026#34;\\t\u0026#34; + empAge); } // 6.释放资源(遵循先开后关原则)--\u0026gt;目前有connection、statement、resultSet三个资源 resultSet.close(); statement.close(); connection.close(); } } 二、核心API理解 2.1注册驱动 1 Class forname(\u0026#34;com.mysql.cj.jdbc.driver\u0026#34;); 注册驱动是为了和数据库通信，加载驱动程序的目的是为了注册驱动程序，使得JDBC API能够识别并且与特定的数据库进行交互。\n从JDK6开始就不需要写Class forname()来加载JDBC驱动程序，只要在类路径中集成了对应的jar文件，会自动在初始化时注册驱动程序。\n2.2 Connection Connection接口是JDBC API的重要接口，用于建立与数据库通信通道，只要Connection不为空，就代表一次与数据库连接。\n在建立连接时，需要指定数据库URL、用户名、密码。\nURL：jdbc:mysql://localhost:3306/jdbcdemo\njdbc:mysql//IP地址:端口号/数据库名称?参数键值对1\u0026amp;参数键值对2\njdbc:mysql://是固定的 localhost对应着IP地址，这里不是固定的，如果说是买了云服务，那么就要写云服务厂商的数据库IP地址 3306对应的端口号，一般默认的是3306。 斜线分割后对应的jdbcdemo对应的是数据库名称，就是当前要操作那个数据库 如果还有参数要设置添加这时候就不要用/了，要用?隔开，然后写key=value 注：如果你用的是自己的IP地址(localhost)和默认端口号(3306)那么这时候url就可以写：com:mysql:///jdbcdemo\nConnection接口还负责管理事务，Connection接口提供了commit和rollback方法，用于提交事务和回滚事务。\n可以创建Statement对象，用于执行SQL语句并与数据库进行交互。\n在用jdbc技术时，必须先获取connection对象(如果没有获取Connection对象后续的操作不复存在)，Connection也代表的是一次链接，在使用完毕后，要释放资源，避免资源占用浪费和泄露。\n2.3 Statement Statement接口用于执行SQL语句并与数据库进行交互。它是JDBC API中的重要接口。通过Statement对象，可以向数据库发送SQL语句并获取执行结果。\n结果可以是一个或多个结果。\n增删改：受影响行数单个数据。 查询：单行单列、多行多列、单行多列等结果。 Statement接口在执行SQL语句时，会产生SQL注入攻击问题：\n当使用Statement执行动态构建的SQL查询时，往往需要将查询条件与SQL语句拼接在一起，直接将参数和SQL语句一并生成，让SQL的查询条件始终为true得到结果。 2.4PreparedStatement PreparedStatement是Statement接口的子接口，用于执行预编译的SQL查询，作用如下： 预编译SQL语句：在创建PreparedStatement时，就会预编译SQL，也就是SQL语句已经固定。 防止SQL注入：PreparedStatement支持参数化查询，将数据作为参数传递到SQL语句中，采用？占位符的方式，将传入的参数用一对单引号(\u0026rsquo;\u0026rsquo;)包裹起来，无论传递什么都作为值，有效防止传入关键字或值导致SQL注入问题 性能提升：PreparedStatement是预编译SQL语句，同一SQL语句多次执行的情况下，可以复用，不必每次重新编译和解析。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.凌奕.base; import java.sql.*; import java.util.Scanner; public class JDBCPrepared { public static void main(String[] args) throws Exception { String url = \u0026#34;jdbc:mysql://localhost:3306/jdbcdemo\u0026#34;; String username = \u0026#34;root\u0026#34;; //password修改成自己设置mysql的密码 String password = \u0026#34;password\u0026#34;; //password修改为mysql设置的密码 Connection connection = DriverManager.getConnection(\u0026#34;jdbc:mysql://localhost:3306/jdbcdemo\u0026#34;, \u0026#34;root\u0026#34;, \u0026#34;password\u0026#34;); PreparedStatement preparedstatement = connection.prepareStatement(\u0026#34;select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_name=?\u0026#34;); Scanner sc = new Scanner(System.in); System.out.println(\u0026#34;请输入姓名\u0026#34;); String name = sc.nextLine(); preparedstatement.setString(1,name); ResultSet resultSet = preparedstatement.executeQuery(); while (resultSet.next()) { int empId = resultSet.getInt(\u0026#34;emp_id\u0026#34;); String empName = resultSet.getString(\u0026#34;emp_name\u0026#34;); double empSalary = resultSet.getDouble(\u0026#34;emp_salary\u0026#34;); int empAge = resultSet.getInt(\u0026#34;emp_age\u0026#34;); System.out.println(empId + \u0026#34;\\t\u0026#34; + empName + \u0026#34;\\t\u0026#34; + empSalary + \u0026#34;\\t\u0026#34; + empAge); } resultSet.close(); preparedstatement.close(); connection.close(); } } 1 select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_name=?； 如果用sql注入的话就是输入：abc\u0026rsquo; or \u0026lsquo;1\u0026rsquo;=\u0026lsquo;1，这时候abc' or '1'='1就会代替问号并且加上两边加上单引号：\n1 select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_name=\u0026#39;abc\u0026#39; or \u0026#39;1\u0026#39;=\u0026#39;1\u0026#39;； 这是后看着虽然和用Statement时候注入的形式一样，但是PreparedStatement会在他们中间加上转义字符，使得他们变成普通的值：\n1 select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_name=\u0026#39;abc\\\u0026#39; or \\\u0026#39;1\\\u0026#39;=\\\u0026#39;1\u0026#39;； **总结：**在实际应用中，不要使用Statement类，因为它有sql注入的漏洞，反而我们要统一的使用Statement的子类PreparedStatement类，它不仅可以防止sql注入还可以提高性能，因为它是预编译的,可以复用不需要每次都编译。总而言之，使用``PreparedStatement`更安全、更高效。\n2.5ResultSet ResultSet是JDBC API中的一个接口，用于从数据库中执行查询语句所返回的结果集，它提供了一种用于遍历和访问查询结果的方式。 遍历结果：ResultSet可以使用**next()**方法将游标移动到结果集的下一行，逐行遍历数据库查询的结果，返回值为boolean类型，true表示有下一行的结果，false表示没有。 获取单列结果：可以通过getXxx的方法获取单列的数据，该方法为重载方法 ，支持索引和列名进行获取。 专业术语\u0026ndash;ORM：\nJDBC全流程：注册驱动\u0026mdash;\u0026gt;获取连接\u0026mdash;\u0026gt;预编译获取PreparedStatement对象\u0026mdash;\u0026gt;编写并执行sql语句\u0026mdash;\u0026gt;遍历结果集\u0026mdash;\u0026gt;资源释放\n案例\u0026mdash;\u0026gt;CURD 查询\u0026ndash;\u0026gt;单行单列： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.凌奕.base; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class TestDemo { public static void main(String[] args) throws Exception { // 1.驱动注册 Class.forName(\u0026#34;com.mysql.cj.jdbc.Driver\u0026#34;); // 2.获取连接---\u0026gt;passowrd修改为mysql设置的密码 Connection connection = DriverManager.getConnection(\u0026#34;jdbc:mysql://localhost:3306/jdbcdemo\u0026#34;, \u0026#34;root\u0026#34;, \u0026#34;password\u0026#34;); // 3.预编译PreparedStatement对象 PreparedStatement preparStatement = connection.prepareStatement(\u0026#34;select count(*) as count from t_emp\u0026#34;); // 4.获取返回值 ResultSet resultSet = preparStatement.executeQuery(); // 5.遍历值 while(resultSet.next()){ int count=resultSet.getInt(\u0026#34;count\u0026#34;); System.out.println(count); } resultSet.close(); preparStatement.close(); connection.close(); } } 查询\u0026ndash;\u0026gt;单行多列： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package com.凌奕.base; import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class JDBCOperation { @Test public void testQuerySingleRow() throws Exception { //注册驱动 Class.forName(\u0026#34;com.mysql.cj.jdbc.Driver\u0026#34;); //获取连接(url、name、password)---\u0026gt;passowrd修改为mysql设置的密码 Connection connection = DriverManager.getConnection(\u0026#34;jdbc:mysql://localhost:3306/jdbcdemo\u0026#34;,\u0026#34;root\u0026#34;,\u0026#34;password\u0026#34;); //预编译获取preparedStatement对象 PreparedStatement preparedStatement=connection.prepareStatement(\u0026#34;select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_id=?\u0026#34;); //给占位符赋值然后执行并获取结果集 preparedStatement.setInt(1,4); ResultSet resultSet=preparedStatement.executeQuery(); //结果集遍历 while(resultSet.next()){ int empId=resultSet.getInt(\u0026#34;emp_id\u0026#34;); String empName=resultSet.getString(\u0026#34;emp_name\u0026#34;); Double empSalary=resultSet.getdouble(\u0026#34;emp_salary\u0026#34;); int empAge=resultSet.getInt(\u0026#34;emp_age\u0026#34;); System.out.println(empId+\u0026#34;\\t\u0026#34;+empName+\u0026#34;\\t\u0026#34;+empSalary+\u0026#34;\\t\u0026#34;+empAge); } //关闭资源 resultSet.close(); preparedStatement.close(); connection.close(); } } 查询\u0026ndash;\u0026gt;多行多列: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package com.凌奕.base; import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class JDBCOperation { @Test public void testQueryMoreRow() throws Exception { // 1.注册驱动 Class.forName(\u0026#34;com.mysql.cj.jdbc.Driver\u0026#34;); // 2.获取连接(url、name、password)---\u0026gt;passowrd修改为mysql设置的密码 Connection connection = DriverManager.getConnection(\u0026#34;jdbc:mysql:///jdbcdemo\u0026#34;, \u0026#34;root\u0026#34;, \u0026#34;password\u0026#34;); // 3.预编译获得preparedStatement对象 PreparedStatement preparedStatement = connection.prepareStatement(\u0026#34;select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_age\u0026gt;?\u0026#34;); // 4.为占位符赋值才能执行sql preparedStatement.setInt(1, 25); ResultSet resultSet = preparedStatement.executeQuery(); // 5.遍历 while (resultSet.next()) { int empId = resultSet.getInt(\u0026#34;emp_id\u0026#34;); String empName = resultSet.getString(\u0026#34;emp_name\u0026#34;); double empSalary = resultSet.getDouble(\u0026#34;emp_salary\u0026#34;); int empAge = resultSet.getInt(\u0026#34;emp_age\u0026#34;); System.out.println(empId + \u0026#34;\\t\u0026#34; + empName + \u0026#34;\\t\u0026#34; + empSalary + \u0026#34;\\t\u0026#34; + empAge); } // 6.资源释放 resultSet.close(); preparedStatement.close(); connection.close(); } } 增加数据: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.凌奕.base; import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class JDBCOperation { @Test public void testInsert() throws Exception { // 1.注册驱动 Class.forName(\u0026#34;com.mysql.cj.jdbc.Driver\u0026#34;); // 2.获取连接(url、name、password)--\u0026gt;passowrd修改为mysql设置的密码 Connection connection = DriverManager.getConnection(\u0026#34;jdbc:mysql:///jdbcdemo\u0026#34;, \u0026#34;root\u0026#34;, \u0026#34;password\u0026#34;); // 3.预编译获取preparedStatement对象 PreparedStatement preparedStatement = connection.prepareStatement(\u0026#34;insert into t_emp(emp_name,emp_salary,emp_age)values(?,?,?)\u0026#34;); preparedStatement.setString(1, \u0026#34;Mike\u0026#34;); preparedStatement.setDouble(2, 9999.99); preparedStatement.setInt(3, 25); int res = preparedStatement.executeUpdate(); // 根据受影响行数判断true或false； if (res \u0026gt; 0) { System.out.println(\u0026#34;True\u0026#34;); } else { System.out.println(\u0026#34;False\u0026#34;); } preparedStatement.close(); connection.close(); } } 更改数据: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.凌奕.base; import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class JDBCOperation { @Test public void testUpdate() throws Exception { Class.forName(\u0026#34;com.mysql.cj.jdbc.Driver\u0026#34;); //passowrd修改为mysql设置的密码 Connection connection = DriverManager.getConnection(\u0026#34;jdbc:mysql:///jdbcdemo\u0026#34;, \u0026#34;root\u0026#34;, \u0026#34;password\u0026#34;); PreparedStatement preparedStatement = connection.prepareStatement(\u0026#34; update t_emp set emp_salary=? where emp_id=?;\u0026#34;); preparedStatement.setDouble(1, 10000); preparedStatement.setInt(2, 6); int res = preparedStatement.executeUpdate(); if (res \u0026gt; 0) { System.out.println(\u0026#34;True\u0026#34;); } else { System.out.println(\u0026#34;False\u0026#34;); } // 关闭资源 preparedStatement.close(); connection.close(); } } 删除数据： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package com.凌奕.base; import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class JDBCOperation { @Test public void testDelete() throws Exception { // 注册驱动 Class.forName(\u0026#34;com.mysql.cj.jdbc.Driver\u0026#34;); // 获取连接 ---\u0026gt;passowrd修改为mysql设置的密码 Connection connection = DriverManager.getConnection(\u0026#34;jdbc:mysql://localhost:3306/jdbcdemo\u0026#34;, \u0026#34;root\u0026#34;, \u0026#34;password\u0026#34;); // 预编译获取preparedStatement对象 PreparedStatement preparedStatement = connection.prepareStatement(\u0026#34;delete from t_emp where emp_id=?\u0026#34;); // 给占位符赋值，执行sql语句获取结果集 preparedStatement.setInt(1, 7); int result = preparedStatement.executeUpdate(); if (result \u0026gt; 0) { System.out.println(\u0026#34;True\u0026#34;); } else { System.out.println(\u0026#34;False\u0026#34;); } // 关闭资源 preparedStatement.close(); connection.close(); } } 在执行sql返回结果的时候：\n如果是查询就用executeQuery()\n如果是增删改就用executeUpdate()\n","date":"2025-08-23T23:01:38+08:00","image":"https://lingyicode.github.io/post/jdbc-%E5%85%A5%E9%97%A8%E5%88%B0%E9%AB%98%E7%BA%A7/MeiGuiHua_hu_d815d5ff1832f7d1.png","permalink":"https://lingyicode.github.io/post/jdbc-%E5%85%A5%E9%97%A8%E5%88%B0%E9%AB%98%E7%BA%A7/","title":"JDBC-入门到高级"}]