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

第四十三天(JavaEE应用ORM框架SQL预编译JDBCMyBatisHibernateMaven)

#Maven配置

参考:IDEA配置maven_idea 配置maven-CSDN博客

Maven 是 Java 生态系统中广泛使用的项目管理和构建自动化工具,主要功能包括:

  1. 依赖管理:自动下载、管理项目所需的第三方库(JAR 包),并处理依赖之间的版本冲突,无需手动下载和复制 JAR 文件。
  2. 标准化项目结构:规定了统一的项目目录结构(如 src/main/java 存放源代码、src/test/java 存放测试代码等),使不同 Java 项目的结构保持一致,降低协作成本。
  3. 构建自动化:通过配置文件(pom.xml)定义项目的构建流程,支持编译、测试、打包(生成 JAR/WAR 等)、部署等一系列操作,可一键执行完整构建过程。
  4. 项目信息管理:在 pom.xml 中可维护项目的基本信息(如名称、版本、开发者等),并能与代码仓库、持续集成工具等集成。

根据参考文档配置好,测试是否正确配置环境

配置时要注意,mirror是否包含在mirrors里面,是否少了 ,如果少了,就会报错了,导致第三方库无法下载下来

#JDBC

参考:JavaEE-JDBC基础 - 简书

新建项目

选好版本和依赖

1、引用依赖(pom.xml)

https://mvnrepository.com/

选择第二个

选择一个版本,别选最新,不然可能不兼容,会报错

选择maven,然后将那段代码复制

将代码复制到里面,然后点击右侧的maven

打开之后点击和刷新很像的符号,然后要注意左侧是否将库下载进去了,如果没有就换一个MySQL存储库

新建一个软件包放服务器的东西,写一个接收id的值,然后写一个查询语句

2、注册数据库驱动

Class.forName("com.mysql.jdbc.Driver");

  • MySQL 5.x 版本的驱动类名是 com.mysql.jdbc.Driver
  • MySQL 8.x 版本才引入 com.mysql.cj.jdbc.Driver 这个新的驱动类名

写上注册语句,这里会报异常,直接用try ,catch 包裹就行,这里用的5.7版本的MySQL和5版本的驱动

3、建立数据库连接

String url ="jdbc:mysql://localhost:3306/phpstudy";

Connection connection=DriverManager.getConnection(url,"root","123456");

测试一下是否连接正常, 连接正常,输出乱码是因为没定义输出的格式

4、创建Statement执行SQL

Statement statement= connection.createStatement();

ResultSet resultSet = statement.executeQuery(sql);

输入id值进行测试

5、结果ResultSet进行提取

 while (rs.next()) {
                resp.getWriter().println(rs.getString("id"));   // 输出名称为id的列的值
                resp.getWriter().println(rs.getString("username"));  // 输出名称为username的列的值
                resp.getWriter().println(rs.getString("password"));  // 输出名称为password的列的值
                resp.getWriter().println(rs.getString(3));  // 输出第三列的值
 
            }

这里查询id为2 的数据,可以正常显示

安全注入例子:

预编译:PreparedStatement

安全写法(预编译): "select * from admin where id=?"

输入的sql注入语句没有生效 ,预编译中将查询语句写死了,在后面写的sql注入语句不会执行

完整代码:

@WebServlet("/jdbc")
public class JdbcServlet extends HttpServlet {
@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String id = req.getParameter("id");
        //安全的拼接SQL语句
//        String sql = "select * from admin where id = ?";
        String url ="jdbc:mysql://localhost:3306/phpstudy";
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = DriverManager.getConnection(url,"root","654321");
            PreparedStatement ps = conn.prepareStatement(sql);   // 创建PreparedStatement对象
            ps.setString(1,id);   // 设置第一个参数的值
            ResultSet rs = ps.executeQuery();  // 执行查询
            while (rs.next()) {
                resp.getWriter().println(rs.getString("id"));   // 输出名称为id的列的值
                resp.getWriter().println(rs.getString("username"));  // 输出名称为username的列的值
                resp.getWriter().println(rs.getString("password"));  // 输出名称为password的列的值
                resp.getWriter().println(rs.getString(3));  // 输出第三列的值
            }
        } catch (ClassNotFoundException | SQLException e) {
            throw new RuntimeException(e);
        }
    }
    }

不安全写法(拼接): "select * from admin where id="+id

可以执行后面的sql注入语句,就可以开始注入了

 

完整代码

@WebServlet("/jdbc")
public class JdbcServlet extends HttpServlet {
@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String id = req.getParameter("id");
        //不安全的拼接SQL语句,容易导致SQL注入攻击
        String sql = "select * from admin where id = "+id;
        String url ="jdbc:mysql://localhost:3306/phpstudy";
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = DriverManager.getConnection(url,"root","654321");
            Statement statement = conn.createStatement();  // 创建Statement对象
            ResultSet rs = statement.executeQuery(sql);  // 执行查询
            while (rs.next()) {
                resp.getWriter().println(rs.getString("id"));   // 输出名称为id的列的值
                resp.getWriter().println(rs.getString("username"));  // 输出名称为username的列的值
                resp.getWriter().println(rs.getString("password"));  // 输出名称为password的列的值
                resp.getWriter().println(rs.getString(3));  // 输出第三列的值
            }
        } catch (ClassNotFoundException | SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

#Hibernate

项目创建和jdbc 一样,就是项目名称改一下

这里勾选一下 hibernate ,等会就不用引用了 (但是测试时用这个依赖库时会报错,可能是后面的id什么对不上或者版本不兼容等)

1、引用依赖(pom.xml)

https://mvnrepository.com/

hibernate-core,mysql-connector-java

创建项目时勾选的引用库

自己写引用

2、Hibernate配置文件

src/main/resources/hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- 数据库连接配置 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/phpstudy?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">654321</property>
 
        <!-- 数据库方言 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
 
        <!-- 显示 SQL 语句 -->
        <property name="hibernate.show_sql">true</property>
 
        <!-- 自动更新数据库表结构 -->
        <property name="hibernate.hbm2ddl.auto">update</property>
 
        <!-- 映射实体类 -->
        <mapping class="com.example.hibermateddemo.entity.User"/>
    </session-factory>
</hibernate-configuration>

3、映射实体类开发

用来存储获取数据:

src/main/java/com/example/entity/User.java

package com.example.hibermateddemo.entity;
 
import javax.persistence.*;
 
@Entity
@Table(name = "admin")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String username;
 
 
    public User() {}
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
 
 
 
    @Override
    public String toString() {
        return "User{id=" + id + ", username=" + username + "}";
    }
}

4、Hibernate工具类

用来Hibernate使用:

src/main/java/com/example/util/HibernateUtil.java

package com.example.hibermateddemo.util;
 
 
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
 
public class HibernateUtil {
    private static final SessionFactory sessionFactory;
 
    static {
        try {
            Configuration configuration = new Configuration().configure();
            sessionFactory = configuration.buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }
 
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

5、Servlet开发接受:

src/main/java/com/example/servlet/UserServlet.java

package com.example.hibermateddemo.servlet;
 
 
 
 
import com.example.hibermateddemo.entity.User;
import com.example.hibermateddemo.util.HibernateUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.hibernate.Session;
 
 
import org.hibernate.Query;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
 
@WebServlet("/user")
public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
 
        // 获取参数(这里假设根据用户名查询)
        String username = request.getParameter("username");
 
        // 打开 Hibernate Session
        Session session = HibernateUtil.getSessionFactory().openSession();
        try {
            // 修改后的 HQL 语句,直接拼接字符串
//            String hql = "FROM User WHERE username = '" + username + "'";
 
            String hql = "FROM User WHERE username=:username";
            // 创建查询对象
            Query<User> query = session.createQuery(hql, User.class);
            query.setParameter("username", username); // 设置参数值
            // 执行查询
            List<User> users = query.getResultList();
 
            // 输出查询结果
            out.println("<html><body>");
            if (users.isEmpty()) {
                out.println("<p>未找到匹配的用户。</p>");
            } else {
                for (User user : users) {
                    out.println("<p>" + user + "</p>");
                }
            }
            out.println("</body></html>");
        } catch (Exception e) {
            e.printStackTrace();
            out.println("<html><body><p>查询出错,请稍后重试。</p></body></html>");
        } finally {
            // 关闭 Session
            session.close();
        }
    }
}
 

完整流程:

1. 启动阶段:Hibernate 初始化
  1. 加载配置文件
    应用启动时,HibernateUtil类被加载,其静态代码块执行:
    • 通过new Configuration().configure()读取类路径下的hibernate.cfg.xml配置文件。
    • 配置文件中包含:数据库连接信息(URL、用户名、密码、驱动)、Hibernate 方言、实体映射等。
  2. 创建 SessionFactory
    • configuration.buildSessionFactory()根据配置信息创建SessionFactory(Hibernate 的核心工厂类,负责管理数据库连接池和会话)。
    • SessionFactory是重量级对象,全局唯一,后续所有数据库操作都通过它创建Session
2. 运行阶段:处理用户请求(以/user请求为例)
步骤 1:接收 HTTP 请求
  • 前端通过/user?username=xxx发送 GET 请求,被@WebServlet("/user")注解的UserServlet拦截。
  • doGet方法被调用,获取请求参数username(用户输入的查询条件)。
步骤 2:获取 Hibernate Session
  • 通过HibernateUtil.getSessionFactory().openSession()SessionFactory获取Session对象。
  • Session是 Hibernate 与数据库交互的会话对象,类似 JDBC 的Connection,用于执行 CRUD 操作。
步骤 3:执行 HQL 查询
  1. 构建查询语句
    • 拼接 HQL 语句:"FROM User WHERE username = '" + username + "'"(根据用户名查询User实体)。
  2. 创建查询对象
    • 通过session.createQuery(hql, User.class)创建Query对象,指定返回结果为User类型。
  3. 执行查询
    • 调用query.getResultList()执行查询,Hibernate 将 HQL 转换为对应数据库的 SQL(如SELECT * FROM user WHERE username = 'xxx'),并发送到数据库。
    • 数据库返回结果后,Hibernate 将结果集映射为User对象列表。
步骤 4:响应查询结果
  • 通过
  • HTML 响应:
    • 若查询结果为空,显示 “未找到匹配的用户”。
    • 若有结果,遍历User列表并输出用户信息。
步骤 5:释放资源
  • finally块中调用session.close()关闭Session,释放数据库连接资源。

安全注入例子: (修改UserServlet.java 中的语句实现效果)

安全写法:String hql = "FROM User WHERE username=:username";

输入正确的值是可以正常查询

用sqlmap 跑一下看是否存在 SQL 注入漏洞 用这个写法是不存在sql注入漏洞的

命令 : python sqlmap.py -u "http://localhost:8080/Hibermated_demo_war_exploded/user?username=xiaodi"

不安全写法:String hql = "FROM User WHERE username='"+username+"'";

这里用正确的username查询一下数据库的数据看一下

 

用sqlmap 跑一下看是否存在 SQL 注入漏洞 用这个写法是存在sql注入漏洞的

#MyBatis

1、引用依赖(pom.xml)

mybatis,mysql-connector-java

在pom.xml 中的 里面加入下面代码

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.13</version>
        </dependency>
<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.17</version>
        </dependency>

要确保引入的库加载到了外部库中,否则是没有成功的

2、MyBatis配置文件

src/main/resources/mybatis-config.xml 文件路径

<?xml version="1.0" encoding="UTF-8" ?>
 
<!DOCTYPE configuration
 
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
 
<configuration>
 
    <environments default="development">
 
        <environment id="development">
 
            <transactionManager type="JDBC"/>
 
            <dataSource type="POOLED">
 
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
 
                <property name="url" value="jdbc:mysql://localhost:3306/phpstudy?serverTimezone=UTC"/>
 
                <property name="username" value="root"/>
 
                <property name="password" value="123456"/>
 
            </dataSource>
 
        </environment>
 
   </environments>
 
   <mappers>
 
        <mapper resource="AdminMapper.xml"/>
 
   </mappers>
 
</configuration>

3、AdminMapper.xml创建

src/main/resources/AdminMapper.xml 文件路径

<?xml version="1.0" encoding="UTF-8" ?>
 
<!DOCTYPE mapper
 
                PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
                "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
        <mapper namespace="com.example.jdbcdemo43.mapper.AdminMapper">
 
            <select id="selectAdminById" resultType="com.example.jdbcdemo43.model.Admin">
 
                SELECT * FROM admin WHERE id = #{id}
 
            </select>
 
        </mapper>

4、创建数据实体类

com/example/mybatisdemo43/model/Admin.java

package com.example.mybatisdemo.model;
 
public class Admin {
    private int id;
    private String username;
    private String password;
 
 
    // Getters and Setters
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
 
    @Override
    public String toString() {
        return "Admin{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
 
                '}';
    }
}

5、创建mapper实体类

com/example/mybatisdemo43/mapper/AdminMapper.java

package com.example.mybatisdemo.mapper;
 
 
import com.example.mybatisdemo.model.Admin;
import org.apache.ibatis.annotations.Param;
 
public interface AdminMapper {
    Admin selectAdminById(@Param("name") String name);
}

6、创建servlet接受类

com/example/mybatisdemo43/servlet/SelectServlet.java

package com.example.mybatisdemo.servlet;
 
import com.example.mybatisdemo.mapper.AdminMapper;
import com.example.mybatisdemo.model.Admin;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 
 
import java.io.IOException;
import java.io.InputStream;
 
@WebServlet(name = "sql", value = "/sql")
public class SelectServlet extends HttpServlet {
 
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
 
        if (name == null || name.isEmpty()) {
            resp.getWriter().write("none");
            return;
        }
 
        // 加载 MyBatis 配置文件
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
 
        // 获取 SqlSession
        try (SqlSession session = sqlSessionFactory.openSession()) {
            // 获取 Mapper 接口
            AdminMapper mapper = session.getMapper(AdminMapper.class);
 
            // 执行查询
            Admin admin = mapper.selectAdminById(name);
 
            // 输出结果
            if (admin != null) {
                resp.getWriter().println("ID: " + admin.getId());
                resp.getWriter().println("用户名: " + admin.getUsername());
                resp.getWriter().println("密码: " + admin.getPassword());
 
            } else {
                resp.getWriter().write("111111no");
            }
        } catch (Exception e) {
            e.printStackTrace();
            resp.getWriter().write("shibai");
        }
    }
}

目录结构:

流程:

  1. mybatis-config.xml
    (最先被加载)程序启动时,MyBatis 首先读取该核心配置文件,解析数据源、事务管理和 Mapper 路径等信息,为后续创建SqlSessionFactory做准备。
  2. SelectServlet.java(核心执行代码)
    (接收请求后执行)当 Servlet 收到请求(doGet方法被调用)时:
    • 先加载mybatis-config.xml创建SqlSessionFactory
    • 再通过SqlSessionFactory获取SqlSession
      这是运行时触发查询的起点。
  3. AdminMapper.java
    (获取代理对象时使用)通过SqlSession.getMapper(AdminMapper.class)获取接口的动态代理对象,此时 MyBatis 会关联接口与对应的映射文件。
  4. AdminMapper.xml
    (执行 SQL 时使用)调用AdminMapper.selectAdminById()方法时,MyBatis 通过namespace+id找到该文件中定义的 SQL 语句,替换参数后执行查询。
  5. Admin.java
    (结果返回时使用)SQL 执行完成后,MyBatis 根据resultType配置,将数据库返回的结果集自动映射为Admin对象,最终在 Servlet 中被处理并响应。
数据流向链路

请求触发 → SelectServlet加载mybatis-config.xml → 创建SqlSessionFactory → 获取SqlSession → 获取AdminMapper代理对象 → 调用方法匹配AdminMapper.xml中的SQL → 执行SQL查询 → 结果映射为Admin对象 → 响应结果

安全注入例子:

1、安全写法: select * from admin where id = #{id}

拿sqlmap跑一下看看是否有能注入 ,这里是没有的

2、不安全写法:select * from admin where id = ${id}

 在AdminMapper.xml 写的查询语句是$

拿sqlmap跑一下看看是否有能注入 ,这里是有的

命令: (要进到sqlmap目录里面打开cmd输入下面命令)

python sqlmap.py -u "http://localhost:8080/mybatis_demo_war_exploded/sql?id=1"

#Spring JPA

由于涉及到开发框架,后续讲到,安全基本和Hibernate相似

http://www.xdnf.cn/news/18499.html

相关文章:

  • 算法训练营day60 图论⑩ Bellman_ford 队列优化算法、判断负权回路、单源有限最短路
  • Vue 3 useModel vs defineModel:选择正确的双向绑定方案
  • [特殊字符] 在 Windows 新电脑上配置 GitHub SSH 的完整记录(含坑点与解决方案)
  • 简单留插槽的方法
  • 生成一个竖直放置的div,宽度是350px,上面是标题固定高度50px,下面是自适应高度的div,且有滚动条
  • 航空复杂壳体零件深孔检测方法 - 激光频率梳 3D 轮廓检测
  • FFMPEG相关解密,打水印,合并,推流,
  • 鸿蒙中Snapshot分析
  • Vue3+ElementPlus倒计时示例
  • 应用服务器和数据库服务器的区别
  • 机器学习案例——预测矿物类型(数据处理部分)
  • [CISCN2019 华北赛区 Day1 Web5]CyberPunk
  • `sudo apt update` 总是失败
  • Linux问答题:调优系统性能
  • 李宏毅NLP-12-语音分类
  • 基于Labview的旋转机械AI智能诊断系统
  • 2015-2018年咸海流域1km归一化植被指数8天合成数据集
  • html-docx-js 导出word
  • Linux问答题:归档和传输文件
  • 探秘北斗卫星导航系统(BDS):架构、应用与未来蓝图,展现中国力量
  • 文件系统挂载详细分析(《图解Linux内核》虚拟文件系统篇笔记二)
  • UDP报文的数据结构
  • 可转换债券高频交易Level-2五档Tick级分钟历史数据分析
  • 20250823解决荣品RD-RK3588-MID核心板的底板的adb不通
  • 超越基础:Glide 高级优化与自定义实战
  • 12.Shell脚本修炼手册--函数的基础认知与实战演练(fock炸弹!!)
  • 第1.2节:早期AI发展(1950-1980)
  • Mybatis Plus - 代码生成器简单使用
  • Baumer高防护相机如何通过YoloV8深度学习模型实现社交距离的检测识别(python)
  • 【204页PPT】某著名企业信息化规划方案(附下载方式)