详解 HBase 的常用 API

一、环境准备

  • 创建一个 Maven 工程并引入依赖

    <dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-server</artifactId><version>1.3.1</version>
    </dependency>
    <dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-client</artifactId><version>1.3.1</version>
    </dependency>
    
  • 创建 API 测试类并获取 HBase 客户端连接

    public class TestAPI {private static Connection conn = null;private static Admin admin = null;  // DDL 操作客户端static {try { // 1.获取配置信息对象// 过时API// HBaseConfiguration conf1 = new HBaseConfiguration();// conf1.set("hbase.zookeeper.quorum","hadoop102,hadoop103,hadoop104");// 新APIConfiguration conf = HBaseConfiguration.create();conf.set("hbase.zookeeper.quorum","hadoop102,hadoop103,hadoop104");// 2.创建连接对象(新API)conn = ConnectionFactory.createConnection(conf);// 3.创建hbase管理员对象// 过时API// HBaseAdmin admin1 = new HBaseAdmin(conf1);// 新APIadmin = conn.getAdmin();} catch(Exception e) {e.printStackTrace();    }}// 关闭资源public static void close() {try {if(admin != null) {admin.close();}if(conn != null) {conn.close();}} catch(Exception e) {e.printStackTrace();}}
    }
    

二、HBase API 实操

1. 判断表是否存在

public static boolean isTableExist(String tableName) {// 过时API// boolean exist = admin1.tableExists(tableName);// 新APIboolean exist = admin.tableExists(TableName.valueOf(tableName));return exist;
}

2. 创建表

public static void createTable(String tableName, String... cfs) {// 1.判断传入列族信息if(cfs.length()<=0) {System.out.println("必须设置一个列族信息");return;}// 2.判断表是否存在if(isTableExist(tableName)) {System.out.println(tableName + "表已经存在");return;}// 3.创建表描述器HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf(tableName));// 4.循环添加列族for(String cfs : cfs) {// 5.创建列族描述器HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(cfs);// 6.添加单个列族hTableDescriptor.addFamily(hColumnDescriptor);}// 7.创建表admin.createTable(hTableDescriptor);System.out.println(tableName + "表创建成功!");
}

3. 删除表

public static void deleteTable(String tableName) {// 1.判断表是否存在if(!isTableExist(tableName)) {System.out.println(tableName + "表已经不存在!");return;}// 2.使表下线admin.disableTable(TableName.valueOf(tableName));// 3.删除表admin.deleteTable(TableName.valueOf(tableName));System.out.println(tableName + "表删除成功!");
}

4. 创建命名空间

public static void createNamespace(String ns) {// 1.创建命名空间描述器NamespaceDescriptor namespaceDescriptor = NamespaceDescriptor.create(ns).build();try {// 2.创建命名空间admin.createNamespace(namespaceDescriptor); System.out.println(ns + "命名空间创建成功!");} catch(NamespaceExistException e) { // 生产上判断 ns 是否存在System.out.println(ns + "命名空间已经存在!");} catch(Exception e) {e.printStackTrace();}}

5. 插入数据

public static void putData(String tableName, String rowKey, String cf, String cn, String value) {// 1.创建hbase表操作对象Table table = conn.getTable(TableName.valueOf(tableName));// 2.创建 put 对象// HBase 底层存储的数据格式都是 byte[],可以通过 hbase.util 包下的 Bytes 类进行数据类型转换Put put = new Put(Bytes.toBytes(rowKey));// 3.给put对象赋值put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(cn), Bytes.toBytes(value));// 4.插入数据table.put(put);// 5.关闭资源table.close();}

6. 获取数据

6.1 get
public static void getData(String tableName, String rowKey, String cf, String cn) {// 1.创建hbase表操作对象Table table = conn.getTable(TableName.valueOf(tableName));// 2.创建get对象Get get = new Get(Bytes.toBytes(rowKey));// 2.1.指定获取的列族// get.addFamily(Bytes.toBytes(cf));// 2.2.指定获取的列族和列// get.addColumn(Bytes.toBytes(cf), Bytes.toBytes(cn));// 2.3.指定获取数据的版本数// get.setMaxVersions();  // 相当于 scan 'tb',{RAW=>TRUE,VERSIONS=>10}// 3.获取一行的数据Result result = table.get(get);// 4.获取一行的所有 cellfor(Cell cell : result.rawCells()) {// 5.打印数据信息System.out.println("family:" + Bytes.toString(CellUtil.cloneFamily(cell)) +",qualifier:" + Bytes.toString(CellUtil.cloneQualifier(cell)) + ",value:" + Bytes.toString(CellUtil.cloneValue(cell)));}// 6.关闭资源table.close();
}
6.2 scan
public static void scanTable(String tableName) {// 1.创建hbase表操作对象Table table = conn.getTable(TableName.valueOf(tableName));// 2.构建scan对象Scan scan = new Scan(); // 全表// Scan scan = new Scan(Bytes.toBytes("1001"),Bytes.toBytes("1003")); // 限定 rowKey 范围,左闭右开// 3.扫描表ResultScanner resultScanner = table.getScanner(scan);// 4.解析resultScannerfor(Result result : resultScanner) { // 按 rowKey 从小到大遍历获取// 5.解析resultfor(Cell cell : result.rawCells()) {// 6.打印数据信息System.out.println("rk:" + Bytes.toString(CellUtil.cloneRow(cell)) +",family:" + Bytes.toString(CellUtil.cloneFamily(cell)) +",qualifier:" + Bytes.toString(CellUtil.cloneQualifier(cell)) + ",value:" + Bytes.toString(CellUtil.cloneValue(cell)));}}// 7.关闭资源table.close();
}

7. 删除数据

delete 操作最终还是 put 操作

public static void deleteData(String tableName, String rowKey, String cf, String cn) {// 1.创建hbase表操作对象Table table = conn.getTable(TableName.valueOf(tableName));// 2.构建delete对象Delete delete = new Delete(Bytes.toBytes(rowKey)); // 相当于 deleteall 命令// 2.1.设置删除列// delete.addColumn(Bytes.toBytes(cf),Bytes.toBytes(cn)); // 删除指定版本的列,不指定则为最大版本,小于该版本的列信息可以查询出来(慎用)// delete.addColumns(Bytes.toBytes(cf),Bytes.toBytes(cn)); // 删除列的所有版本// 2.2.设置删除的列族// delete.addFamily(Bytes.toBytes(cf));// 3.删除数据table.delete(delete);// 4.关闭资源table.close();
}
  • 只指定 rowKey 删除:删除指定 rowKey 的所有列族所有版本数据,标记为 deleteFamily
  • 指定 rowKey + 列族 [+ 版本]:删除指定 rowKey 的指定列族所有版本 (小于等于该版本) 数据,标记为 deleteFamily
  • 指定 rowKey + 列族 + 列 [+ 版本]:
    • addColumns():删除指定 rowKey 的指定列族的指定列的所有版本 (小于等于该版本) 数据,标记为 deleteColumn
    • addColumn():删除指定 rowKey 的指定列族的指定列的最新版本 (该指定版本) 数据,标记为 delete,生产上慎用

三、与 MapReduce 交互

1. 环境搭建

  • 查看 MR 操作 HBase 所需的 jar 包:

    cd /opt/module/hbase
    bin/hbase mapredcp
    
  • 在 Hadoop 中导入环境变量

    • 临时生效:

      # 在命令行执行
      export HBASE_HOME=/opt/module/hbase
      export HADOOP_HOME=/opt/module/hadoop-2.7.2
      export HADOOP_CLASSPATH=`${HBASE_HOME}/bin/hbase mapredcp`
      
    • 永久生效:

      # 在 /etc/profile.d/my_env.sh 配置
      export HBASE_HOME=/opt/module/hbase
      export HADOOP_HOME=/opt/module/hadoop-2.7.2# 在 hadoop-env.sh 中配置,在有关 HADOOP_CLASSPATH 的 for 循环之后添加
      export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:/opt/module/hbase/lib/*
      
  • 分发配置到其他节点

  • 启动 Hadoop 集群和 HBase 集群

2. 案例实操

2.1 官方案例
  • 统计 stu 表中有多少行数据

    /opt/module/hadoop-2.7.2/bin/yarn jar \
    /opt/module/hbase/lib/hbase-server-1.3.1.jar \ 
    rowcounter student
    
  • 使用 MapReduce 将本地数据导入到 HBase

    # 在本地创建一个 tsv 格式的文件:fruit.tsv
    vim fruit.tsv
    1001  Apple  Red
    1002  Pear  Yellow
    1003  Pineapple Yellow# 在 HDFS 中创建 input_fruit 文件夹并上传 fruit.tsv 文件
    /opt/module/hadoop-2.7.2/bin/hdfs dfs -mkdir /input_fruit/
    /opt/module/hadoop-2.7.2/bin/hdfs dfs -put fruit.tsv /input_fruit/# 创建 Hbase 表
    Hbase(main):001:0> create 'fruit','info'# 执行 MapReduce 到 HBase 的 fruit 表中(若表不存在则报错)
    /opt/module/hadoop-2.7.2/bin/yarn jar \
    /opt/module/hbase/lib/hbase-server-1.3.1.jar \
    importtsv -Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:color fruit \
    hdfs://hadoop102:9000/input_fruit/fruit.tsv# 使用 scan 命令查看导入后的结果
    Hbase(main):001:0> scan 'fruit'
    
2.2 自定义案例
  • 案例 1:实现将 HDFS 中的数据写入到 Hbase 表中

    • 编码:

      // 构建 FruitMapper 用于读取 HDFS 中的文件数据
      public class FruitMapper extends Mapper<LongWritable, Text, LongWritable, Text> {@overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {context.write(key, value);}
      }// 构建 FruitReducer 用于将 HDFS 中的文件数据写入 Hbase
      // TableReducer 默认的输出value类型是 Mutation,其子类有 put/delete 等
      public class FruitReducer extends TableReducer<LongWritable, Text, NullWritable> {@overrideprotected void reduce(LongWritable key, Iterable<Text> values, Context context) throws IOException, InterruptedException {// 1.遍历获取每行数据for(Text value : values) {// 2.切割一行数据String[] fields = value.toString().split("\t");// 3.构建put对象Put put = new Put(Bytes.toBytes(fields[0]));// 4.为put对象赋值put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("name"),Bytes.toBytes(fields[1]));put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("color"),Bytes.toBytes(fields[2]));// 5.数据写入hbasecontext.write(NullWritable.get(),put);}}
      }// 构建 FruitDriver
      public class FruitDriver implements Tool {private Configuration conf = null;@overridepublic int run(String[] args) throws Exception {// 1.获取jobJob job = Job.getInstance(conf);// 2.设置驱动类路径job.setJarByClass(FruitDriver.class);// 3.设置Mapper及输出KV类型job.setMapperClass(FruitMapper.class);job.setMapOutputKeyClass(LongWritable.class);job.setMapOutputValueClass(Text.class);// 4.设置Reducer(不能使用普通的 Reducer 设置)TableMapReduceUtil.initTableReducerJob(args[1], FruitReducer.class, job);// 5.设置输入路径FileInputFormat.setInputPaths(job, new Path(args[0]));// 6.提交jobboolean result = job.waitForCompletion(true);return result ? 0 : 1;}@overridepublic void setConf(Configuration conf) {this.conf = conf;}@overridepublic Configuration getConf() {return conf;}public static void main(String[] args) {try {Configuration conf = new Configuration();int status = ToolRunner.run(conf, new FruitDriver(), args);System.exit(status);    } catch(Exception e) {e.printStackTrace();}}
      }
      
    • 将代码打包后上传到 hbase 集群服务器并执行

      # 首先创建 hbase fruit 表
      # 执行:
      /opt/module/hadoop-2.7.2/bin/yarn jar \
      /opt/module/hbase/Hbase-0.0.1-SNAPSHOT.jar com.xxx.FruitDriver \ /input_fruit/fruit.tsv fruit
      
  • 案例 2:将 fruit 表中的一部分数据,通过 MR 迁入到 fruit2 表中

    • 编码

      // 构建 Fruit2Mapper 用于读取 Hbase 中的 Fruit 表数据
      // TableMapper 默认的KV输入类型为 ImmutableBytesWritable, Result
      public class Fruit2Mapper extends TableMapper<ImmutableBytesWritable, Put> {@overrideprotected void map(ImmutableBytesWritable key, Result value, Context context) throws IOException, InterruptedException {// 1.构建PUT对象Put put = new Put(key.get()); // key 是 rowKey 值// 2.解析Resultfor(Cell cell : value.rawCells()) {// 3.获取列为 name 的 cellif("name".equals(Bytes.toString(CellUtil.cloneQualifier(cell)))) {// 4.为put对象赋值put.add(cell);}}// 5.写出context.write(key, put);}
      }// 构建 Fruit2Reducer 用于将数据写入 Hbase
      // TableReducer 默认的输出value类型是 Mutation,其子类有 put/delete 等
      public class Fruit2Reducer extends TableReducer<ImmutableBytesWritable, Put, NullWritable> {@overrideprotected void reduce(ImmutableBytesWritable key, Iterable<Put> values, Context context) throws IOException, InterruptedException {// 遍历写出for(Put put : values) {context.write(NullWritable.get(), put);}}
      }// 构建 Fruit2Driver
      public class Fruit2Driver implements Tool {private Configuration conf = null;@overridepublic int run(String[] args) throws Exception {// 1.获取jobJob job = Job.getInstance(conf);// 2.设置驱动类路径job.setJarByClass(Fruit2Driver.class);// 3.设置Mapper及输出KV类型(不能使用普通的 Mapper 设置)TableMapReduceUtil.initTableMapperJob(args[0], new Scan(), Fruit2Mapper.class, ImmutableBytesWritable.class, Put.class, job);// 4.设置Reducer(不能使用普通的 Reducer 设置)TableMapReduceUtil.initTableReducerJob(args[1], Fruit2Reducer.class, job);// 5.提交jobboolean result = job.waitForCompletion(true);return result ? 0 : 1;}@overridepublic void setConf(Configuration conf) {this.conf = conf;}@overridepublic Configuration getConf() {return conf;}public static void main(String[] args) {try {// Configuration conf = new Configuration();Configuration conf = HbaseConfiguration.create();int status = ToolRunner.run(conf, new Fruit2Driver(), args);System.exit(status);    } catch(Exception e) {e.printStackTrace();}}
      }
      
    • 集群测试:将代码打包后上传到 hbase 集群服务器并执行

      # 首先创建 hbase fruit2 表
      # 执行:
      /opt/module/hadoop-2.7.2/bin/yarn jar \
      /opt/module/hbase/Hbase-0.0.1-SNAPSHOT.jar com.xxx.Fruit2Driver \
      fruit fruit2
      
    • 本地测试:

      • 在 Maven 工程的 resources 目录下创建 hbase-site.xml 文件
      • hbase/conf/hbase-site.xml 的内容拷贝到上面创建的文件中
      • 执行 Fruit2Driver 程序 main 方法

四、集成 Hive

1. 与 Hive 对比

  • Hive
    • 数据仓库:Hive 的本质其实就相当于将 HDFS 中已经存储的文件在 Mysql 中做了一个双射关系,以方便使用 HQL 去管理查询
    • 用于数据分析、清洗:Hive 适用于离线的数据分析和清洗,延迟较高
    • 基于 HDFS、MapReduce:Hive 存储的数据依旧在 DataNode 上,编写的 HQL 语句终将是转换为 MapReduce 代码执行
  • HBase
    • 数据库:是一种面向列族存储的非关系型数据库
    • 用于存储结构化和非结构化的数据:适用于单表非关系型数据的存储,不适合做关联查询,类似 JOIN 等操作
    • 基于 HDFS:数据持久化存储的体现形式是 HFile,存放于 DataNode 中,被 ResionServer 以 region 的形式进行管理
    • 延迟较低,接入在线业务使用:面对大量的企业数据, HBase 可以直线单表大量数据的存储,同时提供了高效的数据访问速度

2. 集成使用

2.1 环境搭建
  • /etc/profile.d/my_env.sh 中配置 Hive 和 HBase 环境变量

    vim /etc/profile.d/my_env.shexport HBASE_HOME=/opt/module/hbase
    export HIVE_HOME=/opt/module/hive
    
  • 使用软链接将操作 HBase 的 Jar 包关联到 Hive

    ln -s $HBASE_HOME/lib/hbase-common-1.3.1.jar $HIVE_HOME/lib/hbase-common-1.3.1.jar
    ln -s $HBASE_HOME/lib/hbase-server-1.3.1.jar $HIVE_HOME/lib/hbaseserver-1.3.1.jar
    ln -s $HBASE_HOME/lib/hbase-client-1.3.1.jar $HIVE_HOME/lib/hbase-client-1.3.1.jar
    ln -s $HBASE_HOME/lib/hbase-protocol-1.3.1.jar $HIVE_HOME/lib/hbase-protocol-1.3.1.jar
    ln -s $HBASE_HOME/lib/hbase-it-1.3.1.jar $HIVE_HOME/lib/hbase-it-1.3.1.jar
    ln -s $HBASE_HOME/lib/htrace-core-3.1.0-incubating.jar $HIVE_HOME/lib/htrace-core-3.1.0-incubating.jar
    ln -s $HBASE_HOME/lib/hbase-hadoop2-compat-1.3.1.jar $HIVE_HOME/lib/hbase-hadoop2-compat-1.3.1.jar
    ln -s $HBASE_HOME/lib/hbase-hadoop-compat-1.3.1.jar $HIVE_HOME/lib/hbase-hadoop-compat-1.3.1.jar
    
  • hive-site.xml 中添加 Zookeeper 连接信息

    <property><name>hive.zookeeper.quorum</name><value>hadoop102,hadoop103,hadoop104</value><description>The  list  of  ZooKeeper  servers  to  talk  to.  This  is only needed for read/write locks.</description>
    </property>
    <property><name>hive.zookeeper.client.port</name><value>2181</value><description>The  port  of  ZooKeeper  servers  to  talk  to.  This  is only needed for read/write locks.</description>
    </property>
    
  • 下载 Hive 对应版本的源码包,使用 Eclipse 工具创建一个普通 Java 工程 import 这个 hbase-handler 文件夹到工程,在工程下创建一个 lib 文件并导入 hive/lib 下所有的 .jar 文件(add build path),使用 export 重新编译 hive-hbase-handler-1.2.2.jar (取消勾选 lib 目录),将新编译的 jar 包替换掉 hive/lib 下的 jar 包

2.2 案例实操
  • 案例 1:建立 Hive 表,关联 HBase 表,插入数据到 Hive 表的同时能够影响 HBase 表

    # 在 Hive 中创建表同时关联 HBase,然后分别进入 Hive 和 HBase 查看
    CREATE TABLE hive_hbase_emp_table
    (empno int,ename string,job string,mgr int,hiredate string,sal double,comm double,deptno int
    )
    STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
    WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,info:ename,info:job,info:mgr,info:hiredate,info:sal,info:comm,info:deptno")
    TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");# 在 Hive 中创建临时中间表,用于 load 文件中的数据
    # 提示:不能将数据直接 load 进 Hive 所关联 HBase 的那张表中
    CREATE TABLE emp
    (empno int,ename string,job string,mgr int, hiredate string,sal double,comm double,deptno int
    )
    row format delimited fields terminated by '\t';# 向 Hive 中间表中 load 数据
    load data local inpath '/home/admin/softwares/data/emp.txt' into table emp;# 通过 insert 命令将中间表中的数据导入到 Hive 关联 Hbase 的那张表中
    insert into table hive_hbase_emp_table select * from emp;# 查看 Hive 以及关联的 HBase 表中是否已经成功的同步插入了数据
    select * from hive_hbase_emp_table;scan 'hbase_emp_table'
    
  • 案例 2:针对已经存在的 HBase 表 hbase_emp_table,在 Hive 中创建一个外部表来关联这张表,并使用 HQL 操作

    # 在 Hive 中创建外部表关联 HBase 表(必须创建外部表)
    CREATE EXTERNAL TABLE relevance_hbase_emp
    (empno int,ename string,job string,mgr int,hiredate string,sal double,comm double,deptno int
    )
    STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
    WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,info:ename,info:job,info:mgr,info:hiredate,info:sal,info:comm,info:deptno") 
    TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");# 使用 HQL 操作
    select * from relevance_hbase_emp;
    

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

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

相关文章

详细描述拍立淘接口的实现过程,包括接口设计、开发、测试、部署等关键步骤

拍立淘接口的实现过程可以详细分为以下几个步骤&#xff1a; 注册与权限获取&#xff1a; 注册成为阿里巴巴开放平台开发者&#xff0c;并创建应用。获取API的调用权限和密钥&#xff08;如AppKey和AppSecret&#xff09;&#xff0c;这些密钥将用于后续的身份验证和请求签名。…

Text2SQL之Vanna优化

文章目录 前言一、优化方向二、干就完了一次性生成多个Question-SQL对先生成一个问题,再根据DDL和业务数据生成SQL总结前言 前阵子写了篇Text2SQL的简单介绍,发现其也是RAG只会,写下了Text2SQL之不装了,我也是RAG 最近也一直在做Text2SQL的优化,于是把自己的一些心得,总…

QSpinBox、QDoubleSpinBox 的使用,进制转换

实现目的 使用QSpinBox、QDoubleSpinBox 实现数量*单价&#xff0c;float结果显示 使用QSpinBox、QDoubleSpinBox 实现进制的转换 拟实现界面 布局 垂直布局、groupBox中为栅格布局 控件进制设置属性 displayIntegerBase 16代表16进制 #include "spinboxexample.h" #…

SpringMVC的控制器方法的一些要点

一、控制器类的注解 1、SpringMVC的控制器类&#xff0c;一般用注解Controller来注释&#xff0c;代表该类是控制器类。 2、如果整个控制器都采用响应体数据返回&#xff0c;那么可以用组合注解 RestController。 二、控制方法的注解 (一)映射请求路径 1、RequestMapping注解…

Algorithm Data Management Cube(ADM-Cube)本科生招募

Algorithm & Data Management Cube&#xff08;算法与数据管理研究小组&#xff0c;A&DM-Cube, http://www.adm-cube.online/ &#xff09;是隶属于天津大学管理与经济学部信息管理与管理科学系/复杂管理系统实验室的研究团队。为了进一步加强团队建设&#xff0c;推动…

ezButton-按钮库

ezButton-按钮库 使用按钮时&#xff0c;初学者通常会遇到以下麻烦&#xff1a; Floating input issue 浮动输入问题Chattering issue 抖动问题Detecting the pressed and released events 检测按下和释放的事件Managing timestamp when debouncing for multiple buttons 在多…

cocosCreator获取手机剪切板内容

最近游戏中需要加上复制粘贴的功能,这个时候就涉及到安卓原生层的东西。步骤如下: 公开文章地址,见个人博客 复制功能 ts代码 调用代码,在需要复制的地方调用即可。 public static copyToClipBoard(str) {if (sys.platform == sys.Platform.ANDROID) {PlatformMgr.callN…

工业设计初学者手册——第四部分:制造工艺

工业设计初学者手册 文章目录 工业设计初学者手册第四部分&#xff1a;制造工艺7. 常见制造工艺介绍7.1 传统制造工艺7.2 现代制造工艺 8. 材料选择与应用8.1 材料的基本分类与特性8.2 材料选择的原则8.3 环保材料的应用 总结 第四部分&#xff1a;制造工艺 7. 常见制造工艺介…

Laravel 中 使用模型作为标志

我最近一直在尝试的一件事是使用模型作为标志&#xff0c;并取得了积极的成果。当你需要以某种方式标记你的一个模型时&#xff0c;你可以在表中添加一个布尔值来指示某种状态。例如&#xff0c;假设你向应用程序添加了一个停用用户的功能。你可以使用如下迁移来更改用户表&…

社团管理系统

用Spring Boot、Vue.js和MyBatis实现社团管理系统 温馨提示&#xff1a;项目源代码获取方式见文末 摘要 本文探讨了如何使用Spring Boot作为后端框架&#xff0c;Vue.js作为前端框架&#xff0c;以及MyBatis作为数据库持久层框架&#xff0c;构建一个社团管理系统。该系统旨…

在Ubuntu上配置和设置防火墙UFW

在本文我们学习如何在Ubuntu上配置和设置UFW&#xff08;防火墙&#xff09;&#xff0c;UFW代表“不复杂的防火墙”&#xff0c;它充当IPTABLES的接口&#xff0c;从而简化了防火墙的配置过程&#xff0c;对于防火墙来说&#xff0c;这是非常困难的。初学者学习和配置防火墙规…

从 PERL 脚本获取输出并将其加载到 MySQL 数据库的解决方案

1、问题背景 有一段 Python 脚本可以调用 Perl 脚本来解析文件&#xff0c;解析后&#xff0c;Perl 脚本会生成一个输出&#xff0c;这个输出将被加载到 Python 脚本中的 MySQL 数据库中。Python 脚本如下&#xff1a; pipe subprocess.Popen(["perl", "./pa…

JSR303校验

校验的需求 前端请求后端接口传输参数&#xff0c;需要校验参数。 在controller中需要校验参数的合法性&#xff0c;包括&#xff1a;必填项校验、数据格式校验等在service中需要校验业务规则&#xff0c;比如&#xff1a;课程已经审核过了&#xff0c;所以提交失败。 servi…

【UML用户指南】-17-对基本行为建模-交互

目录 1、消息的可视化表示 2、对象与角色 3、链和连接件 4、消息 5、序列 6、创建、修改和撤销 7、表示法 8、常用建模技术 8.1、对控制流建模 8.1.1、基于时间的控制流 8.1.2、基于结构的控制流 在任何有意义的系统中&#xff0c;对象都不是孤立存在的&#xff0c;…

Gitlab SSH无法连接但是HTTP可以连接

项目场景&#xff1a; Gitlab在docker中布置好之后测试&#xff0c;发现SSH无法连接但是HTTP可以连接 提示&#xff1a;这是一个无效的源路径 问题描述 http可以识别为git项目&#xff0c;而ssh无法识别成git项目。 原因分析&#xff1a; 三种猜想 端口号被占用 尝试查看…

韩兴国/姜勇团队在《Trends in Plant Science》发表植物根系氮素再分配的观点文章!

氮素是陆地生态系统中的关键限制性营养元素&#xff0c;通过生物固氮和土壤氮供应通常远低高等植物的氮需求。当土壤氮素供应无法充分满足植物茎叶生长需求时&#xff0c;植物会通过自身营养器官&#xff08;如根或根茎&#xff09;再分配来实现氮的内部循环和再利用。尽管植物…

SaaS产品运营|一文讲清楚为什么ToB产品更适合采用PLG模式?

在数字化时代&#xff0c;ToB&#xff08;面向企业&#xff09;产品市场的竞争愈发激烈。为了在市场中脱颖而出&#xff0c;许多企业开始转向PLG&#xff08;产品驱动增长&#xff09;模式。这种模式以产品为核心&#xff0c;通过不断优化产品体验来驱动用户增长和业务发展。本…

RAG未来的出路

总有人喊RAG已死,至少看目前不现实。 持这个观点的人,大多是Long context派,老实说,这派人绝大多数不甚理解长上下文的技术实现点,就觉得反正context越长,越牛B,有点饭圈化 ,当然我并不否认长上下文对提升理解力的一些帮助,就是没大家想的那么牛B而已(说个数据,达到…

2024年ERP软件公司排名前十!

在当今的商业环境中&#xff0c;ERP&#xff08;企业资源规划&#xff09;系统已成为企业日常运营不可或缺的一部分。然而&#xff0c;如何在这众多的ERP系统软件中筛选出最适合自己的一款&#xff0c;成为许多企业共同面临的挑战。今天&#xff0c;我将带大家盘点erp软件公司的…

李沐:用随机梯度下降来优化人生!

大侠幸会&#xff0c;在下全网同名「算法金」 0 基础转 AI 上岸&#xff0c;多个算法赛 Top 「日更万日&#xff0c;让更多人享受智能乐趣」 今天我们来聊聊达叔 6 大核心算法之 —— 优化 算法。吴恩达&#xff1a;机器学习的六个核心算法&#xff01; 梯度下降优化算法是机器…