try ( Connection connection = DriverManager.getConnection(url, "root", "123456"); PreparedStatement statement = connection.prepareStatement(sql); statement.setString(1,username); statement.setString(2,password); ResultSet rs = statement.executeQuery(); )
上述代码为什么不可以?
总结
错误写法 |
问题 |
正确写法 |
try () 中调用方法 |
语法错误,无法编译 |
方法调用移至 try 块内 |
在括号内执行 executeQuery () |
结果集被提前关闭,无法使用 |
嵌套 try-with-resources |
资源声明与方法调用混合 |
违反 try-with-resources 设计原则 |
严格分离资源声明和业务逻辑 |
核心原则:try 的括号内只能用于声明和初始化资源,所有业务逻辑(如设置参数、执行查询)必须放在 try 块内部。
jdbc-mybatias
jdbc写法:
?占位符必须使用预编译,使用预编译之后就不能在进行传参sql执行了
String sql = "select * from user where age >= ? and id <= ? ;"
; PreparedStatement statement = connection.prepareStatement(sql); ResultSet resultSet = statement.executeQuery();,
有占位符?,是不是必须预编译,
预编译之后在进行执行 ResultSet resultSet = statement.executeQuery()是不是不能传sql
@Test public void testUpdate() throws Exception { // 准备工作 //1,加载驱动 //Class.forName("com.mysql.cj.jdbc.Driver");//可以省略 //2.获取数据库连接(建立java程序与mysql数据库通信桥梁) // 通过设置连接字符串、用户名、密码 获取数据库连接 // 连接指定数据库字符串:协议://ip:port/数据库名 , // eg:jdbc:mysql://localhost:3306/db201 // jdbc:mysql: 协议 // localhost ip // 3306 端口 // db201 数据库名 // 如果连接本机数据库服务器可以简写为: jdbc:mysql:///db201 String url = "jdbc:mysql://localhost:3306/db201"; // 获取数据库连接api:会返回java.sql.Connection的实现类ConnectionImpl对象 Connection connection = DriverManager.getConnection(url, "root", "root"); //3.创建执行SQL语句对象(运输货物的货车) Statement statement = connection.createStatement(); //4.执行SQL(使用货车将sql语句运行给mysql数据库去执行) statement.executeUpdate("update user set username = 'abc222' where id = 1"); //5.释放资源 statement.close(); connection.close(); }
解决sql注入写法:
前期的定义不变,执行用?占位符 //4.执行SQL(使用货车将sql语句运行给mysql数据库去执行) String sql = "select * from user where username=? and password=?"; try{ // 获取数据库连接api:会返回java.sql.Connection的实现类ConnectionImpl对象 connection = DriverManager.getConnection(url, "root", "root"); //3.创建执行SQL语句对象(运输货物的货车) statement = connection.prepareStatement(sql);//预编译 statement.setString(1, username); //这里的数字1代表是第一个?(占位符) statement.setString(2, password); //4.执行sql语句 rs = statement.executeQuery();//注意:预编译在执行sql语句的时候不用传递sql
mybatis写法 (使用代理对象)
1. 导入依赖
2.编写application.properties
# 配置数据库连接信息 spring.datasource.url=jdbc:mysql://localhost:3306/db201数据库名称 spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # springboot项目运行端口号 server.port=8080
@Mapper //使用mybatis的注解代替@Repository,mybatis会对象当前类生成代理对象,spring会将代理对象加入spring容器管理 Dao层也可以叫做(Mapper后面更常用)
3.在接口中写sql语句
UserMapper
@Mapper //使用mybatis的注解代替@Repository,mybatis会对象当前类生成代理对象,spring会将代理对象加入spring容器管理 public interface UserMapper { //即是Dao,不用创建实现类,由数据库厂商实现,所以使用动态代理,获取对象交给bean /** * mybatis会自动执行sql语句,并将返回的数据自动映射给List<User> * 如何映射? 答获取结果集的每一行数据,封装为User对象,将User对象添加到List集合中 * 如何将一行数据映射封装成User对象? 答:数据库表中字段名与User类属性名相同会自动映射,使用反射技术 * @return */ @Select("select * from user") List<User> findAll(); } 调用: @Autowired private UserMapper userMapper;//注入的是UserMapper生成的代理对象 @Test public void testFindAll() { List<User> userList = userMapper.findAll(); userList.forEach(user->System.out.println(user));
xml写法:
创建xml文件
eg:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace="com.itheima.mapper.UserMapper" 名称空间映射关联接口--> <mapper namespace="com.itheima.mapper.UserMapper"> <!--映射 UserMapper接口的List<User> findAll2(); 关联sql语句 <select>:执行查询sql语句,标签体是sql语句 id="关联的方法名" id的值要求唯一,所以在mybatis的接口开发里面不可以理由方法重载,否则会报错 resultType="返回值类型",注意如果是集合List<T>只需要T的类型 --> <select id="findAll2" resultType="com.itheima.pojo.User"> select * from user </select> <!-- XML映射文件的默认定义规则? a.XML文件名称与Mapper接口名称一致,并且放置在相同包下(同包同名) b.XML文件的namespace属性为Mapper接口全限定名一致。 c.XML文件中sql语句的id与Mapper接口中的方法名一致。 --> </mapper>
1.类名要与mapper层的接口名一致
2.必须放在与启动类的包或者子包下
此时,接口中可以不写sql语句(均写在yml文件下)
SpringBoot配置文件:yml配置
简化版的application.properties 名称:application.yml
# 数据库连接信息 spring: datasource: url: jdbc:mysql://localhost:3306/db201 username: root password: root type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver # 端口号配置 server: port: 8080 # mybatis日志配置 mybatis: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
application.properties application.yml xml文件(前两种差不多)
配置类型 |
推荐文件名 |
存放位置 |
格式 |
通用配置 |
|
|
YAML(推荐) |
开发环境配置 |
|
|
YAML/Properties |
生产环境配置 |
|
|
YAML/Properties |
MyBatis 映射文件 |
|
|
XML |
名称基本固定(除非加参数指定)
xml文件(生成,在接口的mapper 哪里按alt+回车,自动生成xml文件,但路径要提前配置)
配置项 |
规则 |
命名规则 |
XML 文件必须与 Mapper 接口同名(如 )。 |
存放位置 |
1. 与接口同包(推荐): 或者逻辑同包或者子包:src/resource/com/itheima/mapper/ 原理,编译后包名就都变成了com/itheima/mapper/,其他情况一律不行都要显式调用
|
核心配置 |
- 必须为接口全限定名 需指向 XML 所在路径 |
@RequestBody 用于接收获取请求体json字符串数据 并 转换为java对象,要求对象的属性名与json字符串属性名一致
接受传过来的参数“id”
public Result findById(@PathVariable Integer id){ 形参与传过来的参数名一致过来的
等价于@PathVariable(“id”) Integer id