互联网轻量级框架整合之Spring框架II

news2024/11/23 6:52:34

持久层框架

Hibernate

假设有个数据表,它有3个字段分别是id、rolename、note, 首先用IDEA构建一个maven项目Archetype选择org.apache.maven.archetypes:maven-archetype-quickstart即可,配置如下pom

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>ChapterNew</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>ChapterNew</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>

    <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
    <dependency>
      <groupId>com.mysql</groupId>
      <artifactId>mysql-connector-j</artifactId>
      <version>8.3.0</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.3.7.Final</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>


  </dependencies>
  <build>
    <!--读取配置文件-->
    <resources>
      <resource>
        <directory>src/main/resources</directory>
      </resource>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
  </build>
</project>

根据这个角色表,建立一个POJO(Plain Ordinary Java Object)和这张表的字段对应起来

package com.ssm;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.io.Serializable;
@Entity  //实体类
public class Role implements Serializable{
    @Id //主键
    @GeneratedValue(strategy = GenerationType.AUTO)  //自增
    private int id;
    private String roleName;
    private String note;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }
}


无论是MyBatis还是Hibernate都是依靠某种方法,将数据库的表和POJO映射起来,然后工程师通过操作POJO来完成逻辑开发

数据表有了,POJO类有了,将他们建立起映射关系,则需要提供映射规则,无论是MyBatis或Hibernate都可以使用注解或者XML的方式提供映射规则,因为注解有一定的局限性,通常都会使用XML来完成表和POJO之间的映射规则设定,这就是POJO对象和数据库表相互映射的框架,即对象关系映射(Object Relational Mapping, ORM)框架

无论是MyBatis还是Hibernate都可以被称为ORM框架,只是Hibernate的设计理念完全面向POJO,而MyBatis不是,Hibernate基本不需要编写SQL就可以通过映射关系来操作数据库,它是一种全映射的体现;而MyBatis不同,它需要工程师编写SQL来运行,也因此体现出了两者的很大的区别,MyBatis灵活,几乎可以完全代替JDBC,同时提供了接口编程,MyBatis的数据访问层DAO(Data Access Objects)是不需要实现类的,它只需要一个接口和XML(或者注解),MyBatis提供自动映射、动态SQL、级联、缓存、注解、代码和SQL分离,也因此可以对SQL进行优化,也正是因为其封装少,映射多样化,支持存储过程,可以进行SQL优化等特点,使得他取代Hibernate成为首选

以下是一个基于Hibernate框架的Java Persistence Object (POJO)类与数据库表之间的映射文件示例,假设我们要为一个名为User的实体类创建映射。该映射文件通常命名为User.hbm.xml,并放置在项目的资源目录中,以便被Hibernate自动加载

<!-- t_role.hbm.xml -->
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.ssm.Role" table="t_role">

        <!-- 定义主键 -->
        <id name="id" type="int">
            <column name ="id"/>
            <generator class="identity"/>
        </id>

        <!-- 定义属性映射 -->
        <property name="roleName" type="string">
            <column name="rolename" length="60" not-null="true"/>
        </property>
        <property name="note" type="string">
            <column name="note" length="255"/>
        </property>

        <!-- 如果存在一对多关系,例如每个用户有多个订单 -->
        <!-- <set name="orders" inverse="true" cascade="all-delete-orphan">
            <key column="user_id"/>
            <one-to-many class="com.example.entity.Order"/>
        </set> -->

        <!-- 如果存在一对一关系,例如每个用户有一个头像 -->
        <!-- <one-to-one name="profilePicture" class="com.example.entity.ProfilePicture" cascade="all"/> -->

        <!-- 如果存在多对一关系,例如每个用户属于一个角色 -->
        <!-- <many-to-one name="role" column="role_id" class="com.example.entity.Role" not-null="true"/> -->

        <!-- 如果存在多对多关系,例如每个用户可以关注其他多个用户 -->
        <!-- <bag name="followingUsers" table="user_following">
            <key column="follower_id"/>
            <many-to-many column="following_id" class="com.example.entity.User"/>
        </bag> -->

    </class>
</hibernate-mapping>

解析说明:

  • DOCTYPE声明:指定了使用的Hibernate映射文件DTD版本,确保XML语法正确性。
  • <hibernate-mapping>标签:整个映射配置文件的根节点。
  • <class>标签:
    • name属性指定对应的Java POJO类全名。
    • table属性指定对应的数据库表名。
  • <id>标签:
    • 定义实体类的主键字段。此处以long类型的id为例,对应数据库表中的id列。
    • generator class=“identity” 在Hibernate映射文件中表示所映射的实体类主键字段的生成策略使用数据库的内置标识符生成机制。
  • <property>标签:
    • 对应POJO类中的非主键属性与数据库表中相应列的映射。
    • name属性指定POJO类中的属性名。
    • column属性指定数据库表中的列名。
    • type属性指定数据类型,如string、long、timestamp等。
    • 可选属性如length定义字符串长度限制,not-null和unique分别设置是否允许为空和唯一性约束。
  • 关联关系映射(已注释掉,根据实际需求启用):
    • <set>、<one-to-one>、<many-to-one>、<bag>等标签用于定义不同类型的关联关系,如一对多、一对一、多对一、多对多。
    • 关联关系的具体配置包括关系名称、外键列、目标类、级联操作等。

请根据实际项目中的Role类及其关联关系调整上述映射文件内容。如有其他复杂特性(如继承、嵌套集合等),还需添加相应的映射元素进行配置

Hibernate核心配置文件

<?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.cj.jdbc.Driver</property>
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/ssm1</property>
            <property name="hibernate.connection.username">root</property>
            <property name="hibernate.connection.password">Ms123!@#</property>
            <!-- 使用MYSQL的 innodb引擎 -->
            <property name="hibernate.dialect.storage_engine">innodb</property>

            <!-- 第二部分: 配置hibernate信息  可选的-->
            <!-- 输出底层sql语句 -->
            <property name="hibernate.show_sql">true</property>
            <!-- 输出底层sql语句格式 -->
            <property name="hibernate.format_sql">true</property>
            <!-- hibernate帮创建表,需要配置之后
                update: 如果已经有表,更新,如果没有,创建
            -->
            <property name="hibernate.hbm2ddl.auto">update</property>
            <!-- 配置数据库方言
                在mysql里面实现分页 关键字 limit,只能使用mysql里面
                在oracle数据库,实现分页rownum
                让hibernate框架识别不同数据库的自己特有的语句
             -->
            <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
            <property name="hibernate.connection.autocommit">true</property>
            <!--
            for (non-JTA) DDL execution was not in auto-commit mode;
            the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
            -->
            <!-- 第三部分: 把映射文件放到核心配置文件中 必须的-->
            <mapping resource="mapper/t_role.hbm.xml"/>
        </session-factory>
    </hibernate-configuration>

先对POJO和角色进行映射,再对POJO进行操作,从而影响角表的数据,如下代码所示

package com.ssm;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.junit.Test;

/**
 * Unit test for simple App.
 */
public class RoleTest {
    @Test
    public void testInit() {
        StandardServiceRegistry registry = null;
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction transaction = null;
        try {
            //初始化注册服务对象
            registry = new StandardServiceRegistryBuilder()
                    .configure()//默认加载hibernate.cfg.xml,如果配置文件名称被修改:configure("被修改的名字")
                    .build();
            //获取Session工厂
            sessionFactory = new MetadataSources(registry)
                    .buildMetadata()
                    .buildSessionFactory();
            //从工厂创建Session连接
            session = sessionFactory.openSession();
            //开启事务
            transaction = session.beginTransaction();
            //创建事例
            Role role = new Role();
            role.setRoleName("zhang");
            role.setNote("123");
            session.save(role);
            //提交事务
            transaction.commit();

        } catch (HibernateException e) {
            e.printStackTrace();
            //回滚事务
            transaction.rollback();
        } finally {
            if(session!=null && session.isOpen())
                //关闭session
                session.close();
        }

    }
}

代码中并未写任何SQL,因为Hibernate会根据映射关系生成对应的SQL,应用系统首先考虑的是业务逻辑实现,然后才是性能提升,使用Hibernate的建模方式非常有利于业务分析,因此Hibernate一度成为主流选择

至此一个简单的Hibernate的框架就可以运转起来了,项目结构如下
在这里插入图片描述

MyBatis

前面已经讲了几句MyBatis和Hibernate的些许区别,应该说MyBatis不屏蔽SQL,让它更具灵活性但复杂度也随之而来,但在优化SQL的层面上缺存在巨大的差别,而SQL操作数据往往是系统瓶颈的重要维度之一,因此MyBatis框架逐渐成为了当前Java互联网持久层的首选,它更符合移动互联网高并发、大数据、高性能、快响应的要求,程序员可以自定制定SQL规则,而不是由Hibernate自动生成规则

与Hibernate一样,MyBatis需要一个映射文件把POJO和角色表对应起来

<?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.mapper.RoleMapper">
	<resultMap id="roleMap" type="com.ssm.pojo.Role"/>
		<id property="id" column="id"/>
		<result property="roleName" column="role_name"/>
		<result property="note" column="note"/>
	</resultMap>

    <!-- 插入Role -->
    <insert id="insertRole" parameterType="com.ssm.pojo.Role">
        INSERT INTO t_role(role_name, note)
        VALUES (#{roleName}, #{note})
    </insert>

    <!-- 根据ID查询Role -->
    <select id="getRoleById" parameterType="long" resultMap="roleMap">
        SELECT id, role_name, note FROM t_role WHERE id = #{id}
    </select>

    <!-- 更新Role -->
    <update id="updateRole" parameterType="com.ssm.pojo.Role">
        UPDATE t_role SET role_name = #{roleName}, note = #{note} WHERE id = #{id}
    </update>

    <!-- 删除Role -->
    <delete id="deleteRole" parameterType="long">
        DELETE FROM t_role WHERE id = #{id}
    </delete>
</mapper>

解析说明
在这个MyBatis的Mapper XML文件中:

  • <mapper>元素定义了命名空间(namespace),他要和一个接口的全限定名保持一致
  • resultMap用于定义映射规则,实际上当MyBatis满足一定的规则时,可以自动完成映射
  • 对于每个CRUD操作,分别使用了<insert><select><update><delete>标签来编写SQL语句。
  • id属性指定了在Mapper接口中对应的方法名,也要完全保持一致
  • parameterType属性指定传递给SQL语句的参数类型,这里是com.example.pojo.Role或long。
  • resultType属性(仅在SELECT语句中使用)指定查询结果应映射到的Java类型,也可以类似于XML所写,指定resultMap,Java类在resultMap里指定,这里是com.ssm.pojo.Role
//定义MyBatis映射接口
package com.ssm.chaptertwo.mapper;
import com.ssm.chaptertwo.pojo.Role;
public interface RoleMapper{
	public Role getRole(Integer id);
	public int deleteRole(Integer id);
	public int insertRole(Role role);
	public int update(Role role);
}
//工作这个映射接口完成CRUD
SqlSession sqlSession=null;
try{
	sqlSession = MyBatisUtil.getSqlSession();
	RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
	Role role = roleMapper.getRole(1);//查询
	System.err.println(role.getRoleName());
	role.setRoleName("update_role)name");
	roleMapper.updateRole(role);//更新
	Role role2 = new Role();
	role2.setNote("note2");
	role2.setRoleName("role2");
	roleMapper.insertRole(role);//插入
	roleMapper.deleteRole(5);//删除
	sqlSession.commit();//提交事务catch (Exception ex){
		ex.printStackTrace();
		if(sqlSession!=null){
			sqlSession.rollback();//回滚事务
		}finally{//关闭链接
		if(sqlSession !=null){
			sqlSession.close();
		}
	}

整条链路下来,显然MyBatis在业务逻辑上的实现和Hibernate是大同小异的,区别在于MyBatis需要提供接口和SQL,这意味着他的工作量会大于Hibernate,但由于自定义SQL、映射关系,所以其灵活性和可优化的属性超过了Hibernate 如何取舍完全取决于技术面向业务的业务对象的复杂度

总结对比

  1. Hibernate和MyBatis的CRUD对于业务逻辑来说大同小异,对于映射层,Hibernate的配置不需要接口和SQL,而MyBatis需要
  2. Hibernate不需要编写大量的SQL就可以完全映射,同时提供了日志、缓存、级联(级联比MyBatis强大)等特性,此外还提供了HQL(Hibernate Query Language)对POJO进行操作使用起来很方便,但也存在致命缺陷,由于无须SQL,当关联超过3个表的时候,通过Hibernate的级联会造成很多性能的损失,例如财务表会关联财产信息表,财产信息表又细分为机械、原料等等,很显然这些字段是不一样的,关联字段只能根据特定的条件变化而变化,而Hibernate就不具备这样的灵活性;遇到存储过程Hibernate也无法很好地支持
  3. MyBatis可以自由编写SQL,支持动态SQL、处理列表、动态生成表名、支持存储过程,从而解决了以上Hibernate遇到的问题,更灵活的满足移动互联网的特性系统性能决定了用户忠诚度
  4. MyBatis需要编写SQL和映射规则,工作量会大于Hibernate,且它支持的工具很有限,而Hibernate有许多的插件可以帮助生成映射代码和关联关系,开发者只需要优化或者简化生成内容
  5. 对于性能要求不苛刻的系统,例如管理系统、ERP等使用Hibernate完全可以,对于性能要求较高的系统MyBatis更佳

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1566396.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决Centos7无法连接网络和访问网页连接不上问题

一、网络无法连接问题 网络无法连接的问题我查到了一个很良心的操作&#xff0c;不用重装&#xff0c;因为可能是你虚拟机设置上的问题。我先写我的解决方案&#xff0c;再附上其他几种解决方案。 问题一&#xff1a; 虚拟机的问题****加粗样式 解决&#xff1a; &#xff08;…

自动驾驶传感器:带你搞懂卫星导航GPS-RTK原理

自动驾驶传感器&#xff1a;带你搞懂卫星导航GPS-RTK原理 附赠自动驾驶学习资料和量产经验&#xff1a;链接 0. 前言 自动驾驶的感知层里面&#xff0c;前面Lidar&#xff0c;Radar&#xff0c;Camera的介绍之前已写完。还差GNSS-RTK和IMU模块就补齐了主要的自动驾驶感知层的…

Kubernetes Pod的网络暴露

这里先介绍下Pod的网络暴露&#xff0c;后面复习到service暴露再作更新 一、hostNetwork使用宿主机的网络 1、编写pod-hostnetwork.yaml 配置文件中pod的spec.hostNetwork: true 的配置可实现 apiVersion: v1 kind: Pod metadata:name: pod-hostnetwork spec:hostNetwork: …

一文了解 2024 美国流媒体行业动态

Tubi 每年都会发布流媒体市场研究报告&#xff0c;这既是对流媒体市场的深入参与和贡献&#xff0c;也能帮助广告商深入理解流媒体用户群体和 Tubi 的独特优势。 近日&#xff0c;Tubi 发布了 2024 年美国流媒体市场调研报告&#xff0c;本文将概要介绍其中的关键内容&#xf…

C++——list类及其模拟实现

前言&#xff1a;这篇文章我们继续进行C容器类的分享——list&#xff0c;也就是数据结构中的链表&#xff0c;而且是带头双向循环链表。 一.基本框架 namespace Mylist {template<class T>//定义节点struct ListNode{ListNode<T>* _next;ListNode<T>* _pre…

蓝牙Simple Peripheral工程学习

前言 TI BLE SDK提供了Simple Peripheral工程,初学者可以通过这个工程来学习基本的蓝牙知识,通过实操掌握蓝牙基本的理论与通信方式。 在介绍这个工程前,先为大家介绍蓝牙Peripheral与Central的区别。如下图GAP主要负责Ble设备的连接,GAP状态机描述了设备空闲、设备发现与…

MySQL的基本操作(超详细)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;&#x1f468;&#x1f3fb;‍&#x1f393;告别&#xff0c;今天 &#x1f4d4;高质量专栏 &#xff1a;☕java趣味之旅 &#x1f4d4;&#xff08;零基础&#xff09;专栏&#xff1a;MSQL数据库 欢迎&#x1f64f;点赞&…

计算机网络_工具

从你的电脑到指定ip网站&#xff0c;用时3ms ttl TTL Time To Live 数据包存活时间 指一个数据包在经过一个路由器时&#xff0c;可传递的最长距离&#xff08;跃点数&#xff09;。每当数据包经过一个路由器时&#xff0c;其存活次数就会被减一 256 - 249 7&…

大日志精选案例五:某教育局网络安全与信息化工作稳步推进

“教育网络安全&#xff0c;是保障学校正常运行和教育质量的重要基石。日志&#xff0c;作为记录系统运行和网络访问关键事件的重要载体&#xff0c;对于发现安全隐患和威胁具有不可替代的作用。我们一直在探寻更为高效、精准的日志管理策略。聚铭的大日志方案&#xff0c;成功…

HarmonyOS 应用开发之非线性容器

非线性容器实现能快速查找的数据结构&#xff0c;其底层通过hash或者红黑树实现&#xff0c;包括HashMap、HashSet、TreeMap、TreeSet、LightWeightMap、LightWeightSet、PlainArray七种。非线性容器中的key及value的类型均满足ECMA标准。 HashMap HashMap 可用来存储具有关联…

C语言 | Leetcode C语言题解之第5题最长回文子串

题目&#xff1a; 题解&#xff1a; char* longestPalindrome(char* s) {int lenstrlen(s),max0;int p0;for(int i0;i<len;i)//这种是判断奇数回文{int lefti-1,righti1;//left左边&#xff0c;right右边while(left>0&&right<len&&s[left]s[right]){/…

Linux:logrotate日志轮循分割

比如httpd产生的日志&#xff0c;如果你没做任何设置&#xff0c;他会一直把日志都输出到一个文件中&#xff0c;这个文件会越来越大&#xff0c;httpd就有一个日志切割工具&#xff0c;他可以去分割你的日志&#xff0c;但是无法去轮循日志 日志切割的作用&#xff1a;防止文件…

【氮化镓】同质GaN垂直PiN二极管的SEB

【Single-event burnout in homojunction GaN vertical PiN diodes with hybrid edge termination design. Appl. Phys. Lett. 124, 132101 (2024)https://doi.org/10.1063/5.0189744】 概括&#xff1a; 本研究探讨了具有混合边缘终止设计&#xff08;Hybrid Edge Terminati…

实验2:CLI的使用与IOS基本命令

1、实验目的 通过本实验可以掌握&#xff1a; CLI的各种工作模式个CLI各种编辑命令“?” 和【Tab】键使用方法IOS基本命令网络设备访问限制查看设备的相关信息 2、实验拓扑 CLI的使用与IOS基本命令使用拓扑如下图所示。 3、实验步骤 &#xff08;1&#xff09;CLI模式的切…

PCB设计中的EMC技术

除了元器件的选择和电路设计之外&#xff0c;良好的印制电路板&#xff08;PCB&#xff09;设计在电磁兼容性中也是一个非常重要的因素。PCB EMC设计的关键&#xff0c;是尽可能减小回流面积&#xff0c;让回流路径按照设计的方向流动。最常见返回电流问题来自于参考平面的裂缝…

什么是幂等性?如何解决幂等性问题?

一、什么是幂等性&#xff1f; 幂等&#xff08;idempotence&#xff09;&#xff0c;来源于数学中的一个概念&#xff0c;例如&#xff1a;幂等函数/幂等方法&#xff08;指用相同的参数重复执行&#xff0c;并能获得相同结果的函数&#xff0c;这些函数不影响系统状态&#x…

烂笔头笔记:Windows 11下照片查看器显示偏色问题修复

本文出处&#xff1a;http://blog.csdn.net/chaijunkun/article/details/137278931&#xff0c;转载请注明。由于本人不定期会整理相关博文&#xff0c;会对相应内容作出完善。因此强烈建议在原始出处查看此文。 最近在研究HDR视频的截图算法&#xff0c;目的就是生成色彩正确…

pytest--python的一种测试框架--接口测试

接口测试 工具&#xff1a; POSTMAN&#xff1b; 接口选择&#xff1a; 豆瓣电影&#xff0c;进制数据 POSTMAN下载&#xff1a; 1.POSTMAN官网&#xff1a;https://www.postman.com/products/&#xff1b; 2.点product选Download Postman 下载完之后双击打开就可以用的。…

MVCC的实现原理

简介 MVCC&#xff08;Multi-Version Concurrency Control&#xff09;即多版本并发控制。 MVCC的实现原理 我们在了解MVCC之前&#xff0c;首先先了解一下几个比较常见的锁。 **读锁&#xff1a;**也叫共享锁、S锁&#xff0c;若事务T对数据对象A加上S锁&#xff0c;则事务…