Spring Boot如何整合mybatisplus

文章目录

  • 1. 相关配置和代码
  • 2. 整合原理
    • 2.1 spring boot自动配置
    • 2.2 MybatisPlusAutoConfiguration
    • 2.3 debug流程
      • 2.3.1 MapperScannerRegistrar
      • 2.3.2MapperScannerConfigurer
      • 2.3.3 创建MybatisPlusAutoConfiguration
      • 2.3.4 创建sqlSessionFactory
      • 2.3.5 创建SqlSessionTemplate
      • 2.3.6 mapper接口代理对象创建

1. 相关配置和代码

  • maven
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.14</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.boge</groupId><artifactId>mybatisplus-spring-boot</artifactId><version>0.0.1-SNAPSHOT</version><name>mybatis-spring-boot</name><description>mybatis-spring-boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.18</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter-test</artifactId><version>2.3.1</version><scope>test</scope></dependency><!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version><scope>provided</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
  • application.yml
server:port: 8000
spring:main:allow-circular-references: trueallow-bean-definition-overriding: trueapplication:name: freedom-codedatasource:type: com.alibaba.druid.pool.DruidDataSource# MYSQL 5 驱动:com.mysql.jdbc.Driver,MYSQL 6+ 驱动:com.mysql.cj.jdbc.Driverdriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/mybatis-vip?characterEncoding=utf-8&serverTimezone=UTCusername: rootpassword: sdfsaxs!druid:# 初始化大小,最小,最大initial-size: 5min-idle: 5max-active: 100# 配置获取连接等待超时的时间max-wait: 60000# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位毫秒time-between-eviction-runs-millis: 60000# 配置一个连接在池中最小生存时间min-evictable-idle-time-millis: 300000validation-query: select VERSION()test-while-idle: truetest-on-borrow: falsetest-on-return: false# mybatisplus的配置
mybatis-plus:configuration:# 是否开启自动驼峰命名规则map-underscore-to-camel-case: true# 对所有的 resultMap 都进行自动映射auto-mapping-behavior: full# #控制台打印完整带参数SQL语句log-impl: org.apache.ibatis.logging.stdout.StdOutImplmapper-locations: classpath:mapper/**/*.xmltype-aliases-package: "com.boge.pojo"
@Mapper
public interface UserMapper extends BaseMapper<UserDO> {List<User> query();
}
@Data
@TableName("t_user")
public class UserDO implements Serializable {@TableId(type = IdType.ASSIGN_ID)private Integer id;private String userName;private String password;private String realName;private Integer age;private Integer dId;}
@MapperScan("com.boge.mapper")
@SpringBootApplication
public class MybatisSpringBootApplication {public static void main(String[] args) {SpringApplication.run(MybatisSpringBootApplication.class, args);}}

2. 整合原理

关注三个对象的创建:

  • SqlSessionFactory如何创建
  • SqlSession如何创建
  • Mapper接口的代理类如何创建(比如UserMapper)。

2.1 spring boot自动配置

在这里插入图片描述

2.2 MybatisPlusAutoConfiguration

源码


/*** {@link EnableAutoConfiguration Auto-Configuration} for Mybatis. Contributes a* {@link SqlSessionFactory} and a {@link SqlSessionTemplate}.* <p>* If {@link org.mybatis.spring.annotation.MapperScan} is used, or a* configuration file is specified as a property, those will be considered,* otherwise this auto-configuration will attempt to register mappers based on* the interface definitions in or under the root auto-configuration package.* </p>* <p> copy from {@link org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration}</p>** @author Eddú Meléndez* @author Josh Long* @author Kazuki Shimizu* @author Eduardo Macarrón*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisPlusProperties.class)
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisPlusLanguageDriverAutoConfiguration.class})
public class MybatisPlusAutoConfiguration implements InitializingBean {private static final Logger logger = LoggerFactory.getLogger(MybatisPlusAutoConfiguration.class);private final MybatisPlusProperties properties;private final Interceptor[] interceptors;private final TypeHandler[] typeHandlers;private final LanguageDriver[] languageDrivers;private final ResourceLoader resourceLoader;private final DatabaseIdProvider databaseIdProvider;private final List<ConfigurationCustomizer> configurationCustomizers;private final List<SqlSessionFactoryBeanCustomizer> sqlSessionFactoryBeanCustomizers;private final List<MybatisPlusPropertiesCustomizer> mybatisPlusPropertiesCustomizers;private final ApplicationContext applicationContext;public MybatisPlusAutoConfiguration(MybatisPlusProperties properties,ObjectProvider<Interceptor[]> interceptorsProvider,ObjectProvider<TypeHandler[]> typeHandlersProvider,ObjectProvider<LanguageDriver[]> languageDriversProvider,ResourceLoader resourceLoader,ObjectProvider<DatabaseIdProvider> databaseIdProvider,ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider,ObjectProvider<List<SqlSessionFactoryBeanCustomizer>> sqlSessionFactoryBeanCustomizers,ObjectProvider<List<MybatisPlusPropertiesCustomizer>> mybatisPlusPropertiesCustomizerProvider,ApplicationContext applicationContext) {this.properties = properties;this.interceptors = interceptorsProvider.getIfAvailable();this.typeHandlers = typeHandlersProvider.getIfAvailable();this.languageDrivers = languageDriversProvider.getIfAvailable();this.resourceLoader = resourceLoader;this.databaseIdProvider = databaseIdProvider.getIfAvailable();this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable();this.sqlSessionFactoryBeanCustomizers = sqlSessionFactoryBeanCustomizers.getIfAvailable();this.mybatisPlusPropertiesCustomizers = mybatisPlusPropertiesCustomizerProvider.getIfAvailable();this.applicationContext = applicationContext;}@Overridepublic void afterPropertiesSet() {if (!CollectionUtils.isEmpty(mybatisPlusPropertiesCustomizers)) {mybatisPlusPropertiesCustomizers.forEach(i -> i.customize(properties));}checkConfigFileExists();}private void checkConfigFileExists() {if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());Assert.state(resource.exists(),"Cannot find config location: " + resource + " (please add config file or check your Mybatis configuration)");}}@Bean@ConditionalOnMissingBeanpublic SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {// TODO 使用 MybatisSqlSessionFactoryBean 而不是 SqlSessionFactoryBeanMybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();factory.setDataSource(dataSource);factory.setVfs(SpringBootVFS.class);if (StringUtils.hasText(this.properties.getConfigLocation())) {factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));}applyConfiguration(factory);if (this.properties.getConfigurationProperties() != null) {factory.setConfigurationProperties(this.properties.getConfigurationProperties());}if (!ObjectUtils.isEmpty(this.interceptors)) {factory.setPlugins(this.interceptors);}if (this.databaseIdProvider != null) {factory.setDatabaseIdProvider(this.databaseIdProvider);}if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());}if (this.properties.getTypeAliasesSuperType() != null) {factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType());}if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());}if (!ObjectUtils.isEmpty(this.typeHandlers)) {factory.setTypeHandlers(this.typeHandlers);}if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {factory.setMapperLocations(this.properties.resolveMapperLocations());}// TODO 修改源码支持定义 TransactionFactorythis.getBeanThen(TransactionFactory.class, factory::setTransactionFactory);// TODO 对源码做了一定的修改(因为源码适配了老旧的mybatis版本,但我们不需要适配)Class<? extends LanguageDriver> defaultLanguageDriver = this.properties.getDefaultScriptingLanguageDriver();if (!ObjectUtils.isEmpty(this.languageDrivers)) {factory.setScriptingLanguageDrivers(this.languageDrivers);}Optional.ofNullable(defaultLanguageDriver).ifPresent(factory::setDefaultScriptingLanguageDriver);applySqlSessionFactoryBeanCustomizers(factory);// TODO 此处必为非 NULLGlobalConfig globalConfig = this.properties.getGlobalConfig();// TODO 注入填充器this.getBeanThen(MetaObjectHandler.class, globalConfig::setMetaObjectHandler);// TODO 注入参与器this.getBeanThen(PostInitTableInfoHandler.class, globalConfig::setPostInitTableInfoHandler);// TODO 注入主键生成器this.getBeansThen(IKeyGenerator.class, i -> globalConfig.getDbConfig().setKeyGenerators(i));// TODO 注入sql注入器this.getBeanThen(ISqlInjector.class, globalConfig::setSqlInjector);// TODO 注入ID生成器this.getBeanThen(IdentifierGenerator.class, globalConfig::setIdentifierGenerator);// TODO 设置 GlobalConfig 到 MybatisSqlSessionFactoryBeanfactory.setGlobalConfig(globalConfig);return factory.getObject();}/*** 检查spring容器里是否有对应的bean,有则进行消费** @param clazz    class* @param consumer 消费* @param <T>      泛型*/private <T> void getBeanThen(Class<T> clazz, Consumer<T> consumer) {if (this.applicationContext.getBeanNamesForType(clazz, false, false).length > 0) {consumer.accept(this.applicationContext.getBean(clazz));}}/*** 检查spring容器里是否有对应的bean,有则进行消费** @param clazz    class* @param consumer 消费* @param <T>      泛型*/private <T> void getBeansThen(Class<T> clazz, Consumer<List<T>> consumer) {if (this.applicationContext.getBeanNamesForType(clazz, false, false).length > 0) {final Map<String, T> beansOfType = this.applicationContext.getBeansOfType(clazz);List<T> clazzList = new ArrayList<>();beansOfType.forEach((k, v) -> clazzList.add(v));consumer.accept(clazzList);}}// TODO 入参使用 MybatisSqlSessionFactoryBeanprivate void applyConfiguration(MybatisSqlSessionFactoryBean factory) {// TODO 使用 MybatisConfigurationMybatisConfiguration configuration = this.properties.getConfiguration();if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {configuration = new MybatisConfiguration();}if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {for (ConfigurationCustomizer customizer : this.configurationCustomizers) {customizer.customize(configuration);}}factory.setConfiguration(configuration);}private void applySqlSessionFactoryBeanCustomizers(MybatisSqlSessionFactoryBean factory) {if (!CollectionUtils.isEmpty(this.sqlSessionFactoryBeanCustomizers)) {for (SqlSessionFactoryBeanCustomizer customizer : this.sqlSessionFactoryBeanCustomizers) {customizer.customize(factory);}}}@Bean@ConditionalOnMissingBeanpublic SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {ExecutorType executorType = this.properties.getExecutorType();if (executorType != null) {return new SqlSessionTemplate(sqlSessionFactory, executorType);} else {return new SqlSessionTemplate(sqlSessionFactory);}}/*** This will just scan the same base package as Spring Boot does. If you want more power, you can explicitly use* {@link org.mybatis.spring.annotation.MapperScan} but this will get typed mappers working correctly, out-of-the-box,* similar to using Spring Data JPA repositories.*/public static class AutoConfiguredMapperScannerRegistrarimplements BeanFactoryAware, EnvironmentAware, ImportBeanDefinitionRegistrar {private BeanFactory beanFactory;private Environment environment;@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {if (!AutoConfigurationPackages.has(this.beanFactory)) {logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.");return;}logger.debug("Searching for mappers annotated with @Mapper");List<String> packages = AutoConfigurationPackages.get(this.beanFactory);if (logger.isDebugEnabled()) {packages.forEach(pkg -> logger.debug("Using auto-configuration base package '{}'", pkg));}BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);builder.addPropertyValue("processPropertyPlaceHolders", true);builder.addPropertyValue("annotationClass", Mapper.class);builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages));BeanWrapper beanWrapper = new BeanWrapperImpl(MapperScannerConfigurer.class);Set<String> propertyNames = Stream.of(beanWrapper.getPropertyDescriptors()).map(PropertyDescriptor::getName).collect(Collectors.toSet());if (propertyNames.contains("lazyInitialization")) {// Need to mybatis-spring 2.0.2+// TODO 兼容了mybatis.lazy-initialization配置builder.addPropertyValue("lazyInitialization", "${mybatis-plus.lazy-initialization:${mybatis.lazy-initialization:false}}");}if (propertyNames.contains("defaultScope")) {// Need to mybatis-spring 2.0.6+builder.addPropertyValue("defaultScope", "${mybatis-plus.mapper-default-scope:}");}// for spring-nativeboolean injectSqlSession = environment.getProperty("mybatis.inject-sql-session-on-mapper-scan", Boolean.class,Boolean.TRUE);if (injectSqlSession && this.beanFactory instanceof ListableBeanFactory) {ListableBeanFactory listableBeanFactory = (ListableBeanFactory) this.beanFactory;Optional<String> sqlSessionTemplateBeanName = Optional.ofNullable(getBeanNameForType(SqlSessionTemplate.class, listableBeanFactory));Optional<String> sqlSessionFactoryBeanName = Optional.ofNullable(getBeanNameForType(SqlSessionFactory.class, listableBeanFactory));if (sqlSessionTemplateBeanName.isPresent() || !sqlSessionFactoryBeanName.isPresent()) {builder.addPropertyValue("sqlSessionTemplateBeanName",sqlSessionTemplateBeanName.orElse("sqlSessionTemplate"));} else {builder.addPropertyValue("sqlSessionFactoryBeanName", sqlSessionFactoryBeanName.get());}}builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(MapperScannerConfigurer.class.getName(), builder.getBeanDefinition());}@Overridepublic void setBeanFactory(BeanFactory beanFactory) {this.beanFactory = beanFactory;}@Overridepublic void setEnvironment(Environment environment) {this.environment = environment;}private String getBeanNameForType(Class<?> type, ListableBeanFactory factory) {String[] beanNames = factory.getBeanNamesForType(type);return beanNames.length > 0 ? beanNames[0] : null;}}/*** If mapper registering configuration or mapper scanning configuration not present, this configuration allow to scan* mappers based on the same component-scanning path as Spring Boot itself.*/@org.springframework.context.annotation.Configuration@Import(AutoConfiguredMapperScannerRegistrar.class)@ConditionalOnMissingBean({MapperFactoryBean.class, MapperScannerConfigurer.class})public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {@Overridepublic void afterPropertiesSet() {logger.debug("Not found configuration for registering mapper bean using @MapperScan, MapperFactoryBean and MapperScannerConfigurer.");}}@Order@Bean@ConditionalOnMissingBeanpublic DdlApplicationRunner ddlApplicationRunner(@Autowired(required = false) List<IDdl> ddlList) {if (ObjectUtils.isEmpty(ddlList)) {return null;}return new DdlApplicationRunner(ddlList);}
}

2.3 debug流程

2.3.1 MapperScannerRegistrar

主要为MapperScannerConfigurer定制beanDefinition
在这里插入图片描述

在这里插入图片描述

2.3.2MapperScannerConfigurer

MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor。

方法postProcessBeanDefinitionRegistry可以修改beanDefinition信息。为mapper接口定制beanDefinition。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.3.3 创建MybatisPlusAutoConfiguration

在这里插入图片描述

2.3.4 创建sqlSessionFactory

这里用MybatisSqlSessionFactoryBean来创建sqlSessionFactory。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
重点看buildSqlSessionFactory方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.3.5 创建SqlSessionTemplate

在这里插入图片描述

2.3.6 mapper接口代理对象创建

在这里插入图片描述
打断点到MybatisMapperRegistry
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

科研热点|5本Scopus期刊不再被收录,Scopus期刊目录更新(附下载)!

此次Scopus期刊目录更新后&#xff0c;有5本期刊不再被收录&#xff08;Discontinued titles July 2023&#xff09;&#xff0c;同上次更新时相比&#xff0c;此次又新增139本期刊(Accepted titles)进入Scopus数据库。目前Scopus 来源出版物列表&#xff08;Scopus Sources&am…

全志F1C200S嵌入式驱动开发(soc系统集成)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 任何一个嵌入式设备都是由很多的子系统组成的。这里面有硬件、有软件,还可能有机械,并不一定就是大家看到的消费电子那样,即一个soc构成了所有的系统。现实情况是,要构建一个系…

使用Python将图像转换为PDF:一次性解决您的批量转换需求

导语&#xff1a; 在数字化时代&#xff0c;我们经常需要处理大量的图像文件。将这些图像转换为PDF格式可以方便地存档、分享和打印。本文将介绍如何使用Python编程语言将图像批量转换为PDF&#xff0c;并提供了一个简单易用的图形界面来跟踪转换进度。 准备工作 在开始之前…

一个Linux驱动工程师必知的内核编译机制

Linux内核的编译主要过程&#xff1a;配置、编译、安装。 配置主要由Kconfig提供图形界面完成编译主要基于Kbuild编译系统&#xff0c;执行make完成编译安装主要也是基于Kbuild提供的脚本&#xff0c;然后执行make完成安装 Kconfig Kconfig用于内核的配置&#xff0c;make m…

Kafka入门,保姆级教学

文章目录 Kafka概念消息中间件对比消息中间件对比-选择建议Kafka常用名词介绍Kafka入门1. Kafka安装配置2.Kafka生产者与消费者关系3.Kafka依赖4.生产者发消息5.消费者接受消息6.Kafka高可用性设计6.1集群Kafka备份机制(Reolication) 7.kafka生产者详解7.1 发送类型7.2参数详解…

任务12、Quality指令加持,Midjourney生成电影级数码作品

12.1 任务概述 本次实验任务旨在帮助你掌握Midjourney AI绘画中的Quality指令。通过深入介绍Quality指令的概念和作用,我们将解释为什么它在绘画中至关重要。通过测试不同的Quality参数对绘画效果的影响,并提供实战演示,你将学会如何在Midjourney中设置Quality参数以达到更…

背包问题一维写法(状态压缩)实战,其二(目标和、零一和)

给定一个非负整数数组&#xff0c;a1, a2, ..., an, 和一个目标数&#xff0c;S。现在你有两个符号 和 -。对于数组中的任意一个整数&#xff0c;你都可以从 或 -中选择一个符号添加在前面。 返回可以使最终数组和为目标数 S 的所有添加符号的方法数。 示例&#xff1a; 输…

node上传文件 + vue3 + elementPlus 组件封装

一、node 1.在node环境中安装multer(node.js中间件)包&#xff0c;用于处理 multipart/form-data 类型的表单数据 npm install --save multer 2.userRouter var express require(express); const multer require(multer) const upload multer({ dest: public/avataruplo…

“实现数字化转型:探索会议OA项目的高级技术与创新应用“

文章目录 引言&#xff1a;1.项目背景和需求分析&#xff1a;2.技术选型和架构设计&#xff1a;3.项目实现和功能亮点&#xff1a;3.0 layui实现登录及注册3.1 会议管理模块3.1.1 会议发布3.1.2 我的会议3.1.3 我的审批3.1.4 会议通知3.1.5 待开会议3.1.6 历史会议3.1.7 所有会…

学生管理系统(升级版)

import java.util.ArrayList; import java.util.Random; import java.util.Scanner;public class Demo_学生管理系统 {public static void main(String[] args) {ArrayList<User> list new ArrayList<>();Scanner sc new Scanner(System.in);while (true) {Syste…

浅谈新电改背景下电网企业综合能源服务商业模式研究及发展方向

安科瑞 华楠 摘要: 新电改方案实施后&#xff0c;由于输配电价的改革和售电侧的放开&#xff0c;电网企业的盈利模式也随之发生了变化。这就要求电网企业转变服务理念与经营方式&#xff0c;来寻求竞争优势。基于“魏朱六要素商业模式”模型&#xff0c;对电网企业综合能源服务…

每天五分钟机器学习:梯度下降算法和正规方程的比较

本文重点 梯度下降算法和正规方程是两种常用的机器学习算法,用于求解线性回归问题。它们各自有一些优点和缺点,下面将分别对它们进行详细的讨论。 区别 1. 梯度下降算法是一种迭代的优化算法,通过不断迭代调整参数来逼近最优解。它的基本思想是根据目标函数的梯度方向,沿…

陪诊小程序开发|陪诊系统定制|数字化医疗改善就医条件

健康问题这几年成为人们关注的焦点之一&#xff0c;然而看病却是一个非常麻烦的过程&#xff0c;特别是对于那些身处陌生城市或者不熟悉就医流程的人来说。幸运的是现在有了陪诊小程序下&#xff0c;为您提供便捷的助医服务&#xff0c;使得就医过程得更加简单和轻松。 陪诊系统…

项目管理和产品管理之间的区别

产品管理和项目管理是两个在企业中至关重要的职能部门&#xff0c;它们各自承担着不同的职责和任务。虽然两者在某些方面存在重叠&#xff0c;但它们的核心目标和方法有很大的不同。本文将对产品管理和项目管理进行详细的比较和分析。 “项目管理和产品管理有什么区别&#xff…

赴日IT培训 赴日程序员工作适合什么人?

日本作为全球第三大经济体&#xff0c;IT行业发展十分迅速&#xff0c;日本拥有世界领先的科技公司&#xff0c;如索尼、丰田、日立等&#xff0c;这为IT行业提供了广阔的发展平台和良好的职业前景。此外&#xff0c;日本政府对IT行业也给予了充分的政策支持&#xff0c;像是对…

了解 spring MVC + 使用spring MVC - springboot

前言 本篇介绍什么是spring MVC &#xff0c;如何使用spring MVC&#xff0c;了解如何连接客户端与后端&#xff0c;如何从前端获取各种参数&#xff1b;如有错误&#xff0c;请在评论区指正&#xff0c;让我们一起交流&#xff0c;共同进步&#xff01; 文章目录 前言1. 什么…

C语言单链表OJ题(较难)

一、链表分割 牛客网链接 题目描述&#xff1a; 现有一链表的头指针 ListNode* pHead&#xff0c;给一定值x&#xff0c;编写一段代码将所有小于x的结点排在其余结点之前&#xff0c;且不能改变原来的数据顺序&#xff0c;返回重新排列后的链表的头指针。 思路&#xff1a;…

java+springboot+mysql员工工资管理系统

项目介绍&#xff1a; 使用javaspringbootmysql开发的员工工资管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、员工角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;部门管理&#xff1b;员工管理&#xff1b;奖惩管理&…

【BASH】回顾与知识点梳理(六)

【BASH】回顾与知识点梳理 六 六. 管线命令 (pipe)6.1 撷取命令&#xff1a; cut, grepcutgrep 6.2 排序命令&#xff1a; sort, wc, uniqsortuniqwc 6.3 双向重导向&#xff1a; tee6.4 字符转换命令&#xff1a; tr, col, join, paste, expandtrcoljoinpasteexpand 6.5 分区命…

element-ui - $prompt非空验证

//点击删除按钮 delStoreFun(data) { let than this; this.$prompt(删除门店请填写备注, 提示, { confirmButtonText: 确定, cancelButtonText: 取消, inputValidator: (value) > { //非空验证 if (!value) { return 输入不能为空 } }, }).then(({ value }) > { delS…