insert into时(string->bigint)自动类型转换

本文探讨了Hive中从string类型转换为bigint类型的自动转换过程,并详细分析了一个具体案例,其中涉及到UDFToLong函数如何处理无法转换的string值。文章还讨论了异常处理方式及其背后的逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

原表src:

hive> desc src;
OK
key	string	
value	string	
Time taken: 0.148 seconds
hive> select * from src;
OK
238	val_238
Time taken: 0.107 seconds

建一个新的表create table src111(key bigint, value bigint); 
insert数据到src111表中 insert into table src111 select * from src; 
src的两个字段都是string,src111的两个表都是bigint,hive会做自动转换,通过UDFToLong这个udf自动把string转换成bigint,但是value值val_238无法转换成long 所以src111的值是:

hive> select * from src111;                              
OK
238	0
Time taken: 0.107 seconds

UDFToLong在做类型转换时,如果string无法转换成long会得到NumberFormatException异常,但是这个异常没有被抛出。。。

} catch (NumberFormatException e) {
   // MySQL returns 0 if the string is not a well-formed numeric value.
   // return LongWritable.valueOf(0);
   // But we decided to return NULL instead, which is more conservative.
   return null;
}
<think>我们之前已经完成了Sharding-JDBCCore和SpringBoot的集成,并实现了自定义分片算法。现在用户的需求是集成Sharding-JDBCCore和MyBatis-Plus,并配置自定义hash算法,同创建两张order表,并实现新增数据的接口。根据用户新的需求,我们需要调整一些步骤,特别是在MyBatis-Plus集成方面。步骤:1.依赖:需要添加MyBatis-Plus的依赖,并且由于MyBatis-Plus已经包含了MyBatis,因此可以移除之前配置中的MyBatis-Spring-Boot-Starter。2.自定义分片算法:保持不变。3.配置:在application.yml中配置Sharding-JDBC,并注意MyBatis-Plus的配置(比如mapper扫描位置)。4.数据库表:保持不变,创建两张order表(order_0,order_1)。5.实体类:使用MyBatis-Plus的注解(如@TableName,注意这里逻辑表名是order,所以需要配置逻辑表)6.Mapper:接口需要继承BaseMapper,并且不需要写XML,因为MyBatis-Plus提供了CRUD方法。7.服务层和控制器:与之前类似,但注意使用MyBatis-Plus的Mapper进行插入。详细步骤:1.修改pom.xml,添加MyBatis-Plus依赖,并移除之前的mybatis-spring-boot-starter(如果之前有的话,但现在我们之前用的是MyBatis-Spring-Boot,现在要换成MyBatis-Plus)。注意:Sharding-JDBC和MyBatis-Plus可以兼容。2.自定义分片算法类不变,还是CustomHashShardingAlgorithm。3.配置application.yml,注意以下几点:-配置Sharding-JDBC的数据源和分片规则(表规则,使用自定义算法)。-配置MyBatis-Plus的相关项,比如mapper扫描位置,别名包等。4.创建实体类Order,使用MyBatis-Plus注解,因为我们的表是分片的,所以逻辑表是order,物理表是order_0,order_1。在实体类上使用@TableName("order"),因为Sharding-JDBC会将逻辑表order路由到物理表。5.创建Mapper接口,继承BaseMapper<Order>,这样就有了基本的CRUD方法。6.编写Service和Controller,调用Mapper的insert方法。具体代码:1.依赖(pom.xml):```xml<dependencies><!--SpringBootWeb--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--MyBatis-Plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version><!--请使用最新版本--></dependency><!--Sharding-JDBC--><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-core</artifactId><version>4.1.1</version><!--根据实际情况选择版本--></dependency><!--MySQL驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--Lombok(可选)--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies>```2.自定义分片算法(同上):```javaimportorg.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;importorg.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;importjava.util.Collection;publicclassCustomHashShardingAlgorithmimplementsPreciseShardingAlgorithm<Long>{@OverridepublicStringdoSharding(Collection<String>tableNames,PreciseShardingValue<Long>shardingValue){inttableIndex=Math.abs(shardingValue.getValue().hashCode())%tableNames.size();for(StringtableName:tableNames){if(tableName.endsWith("_"+tableIndex)){returntableName;}}thrownewUnsupportedOperationException("无法路由到表:"+shardingValue);}}```3.配置文件application.yml:```yamlspring:shardingsphere:datasource:names:ds0ds0:type:com.zaxxer.hikari.HikariDataSourcedriver-class-name:com.mysql.cj.jdbc.Driverjdbc-url:jdbc:mysql://localhost:3306/sharding_db?useSSL=false&serverTimezone=UTCusername:rootpassword:rootsharding:tables:order:actual-data-nodes:ds0.order_$->{0..1}#对应两个表:order_0,order_1table-strategy:standard:sharding-column:order_idprecise-algorithm-class-name:com.example.sharding.algorithm.CustomHashShardingAlgorithmprops:sql:show:true#打印SQL#MyBatis-Plus配置mybatis-plus:configuration:log-impl:org.apache.ibatis.logging.stdout.StdOutImpl#打印SQL(可选)mapper-locations:classpath:mapper/*.xml#如果有XML文件,配置路径type-aliases-package:com.example.sharding.model#实体类包```4.实体类Order.java:```javapackagecom.example.sharding.model;importcom.baomidou.mybatisplus.annotation.TableName;importlombok.Data;importjava.math.BigDecimal;importjava.util.Date;@Data@TableName("order")//指定逻辑表名publicclassOrder{privateLongorderId;privateIntegeruserId;privateBigDecimalamount;privateDatecreateTime;}```5.Mapper接口OrderMapper.java:```javapackagecom.example.sharding.mapper;importcom.baomidou.mybatisplus.core.mapper.BaseMapper;importcom.example.sharding.model.Order;publicinterfaceOrderMapperextendsBaseMapper<Order>{}```6.需要在SpringBoot启动类上添加@MapperScan注解扫描Mapper:```javapackagecom.example.sharding;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.mybatis.spring.annotation.MapperScan;@SpringBootApplication@MapperScan("com.example.sharding.mapper")//指定Mapper接口所在的包publicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.run(Application.class,args);}}```7.创建Service和Controller:由于MyBatis-Plus的BaseMapper已经提供了insert方法,我们可以直接使用。Service:```javapackagecom.example.sharding.service;importcom.example.sharding.mapper.OrderMapper;importcom.example.sharding.model.Order;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;@ServicepublicclassOrderService{@AutowiredprivateOrderMapperorderMapper;publicvoidcreateOrder(Orderorder){orderMapper.insert(order);//调用MyBatis-Plus的insert方法}}```Controller:```javapackagecom.example.sharding.controller;importcom.example.sharding.model.Order;importcom.example.sharding.service.OrderService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RequestBody;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassOrderController{@AutowiredprivateOrderServiceorderService;@PostMapping("/order")publicStringcreateOrder(@RequestBodyOrderorder){orderService.createOrder(order);return"订单创建成功";}}```8.创建两张物理表(在数据库中执行):```sql--数据库sharding_db中创建两张表CREATETABLE`order_0`(`order_id`bigint(20)NOTNULL,`user_id`int(11)NOTNULL,`amount`decimal(10,2)DEFAULTNULL,`create_time`datetimeDEFAULTNULL,PRIMARYKEY(`order_id`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;CREATETABLE`order_1`(`order_id`bigint(20)NOTNULL,`user_id`int(11)NOTNULL,`amount`decimal(10,2)DEFAULTNULL,`create_time`datetimeDEFAULTNULL,PRIMARYKEY(`order_id`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;```9.测试:启动应用,通过POST请求/order接口,传入JSON数据:```json{"orderId":123456789,"userId":1001,"amount":199.99,"createTime":"2023-06-15T10:30:00"}```观察控制台日志,可以看到插入的SQL语句,并且根据orderId的哈希值路由到具体的表(order_0或order_1)。注意事项:1.确保数据库连接信息正确。2.自定义分片算法的全类名在配置中要写正确。3.实体类中的字段名和数据库表中的列名要一致(或者使用@TableField注解指定映射)。4.由于我们使用了MyBatis-Plus,插入操作不需要指定主键生成策略(除非有特殊要求)。这里我们直接使用传入的orderId作为主键,并且作为分片键。如果orderId需要自增,那么需要考虑分布式主键生成策略(比如ShardingSphere提供了雪花算法等),但是在这个场景中,我们直接由应用传入orderId。以上就是集成Sharding-JDBCCore和MyBatis-Plus,并配置自定义hash分片算法,以及实现新增订单接口的完整步骤。注意:在分库分表的情况下,如果涉及到跨库跨表的查询,需要特别注意,尽量使用分片键进行查询,避免全路由。生成的相关问题:1.如何验证分片算法的数据分布是否均匀?2.在MyBatis-Plus中如何配置Sharding-JDBC的分库分表?3.自定义分片算法如何同处理分库和分表的路由?4.使用MyBatis-Plus的Wrapper条件构造器进行查询,Sharding-JDBC如何路由?5.如何实现分布式主键生成策略(如雪花算法)并与Sharding-JDBC集成?</think> 以下是在Spring Boot项目中集成Sharding-JDBC Core和MyBatis-Plus,并配置自定义哈希分片算法的完整实现方案: --- ### 1. 添加依赖 (`pom.xml`) ```xml <dependencies> <!-- Spring Boot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MyBatis-Plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> </dependency> <!-- Sharding-JDBC --> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-core</artifactId> <version>5.3.2</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> ``` --- ### 2. 自定义哈希分片算法 ```java import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm; import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue; import java.util.Collection; public class CustomHashShardingAlgorithm implements PreciseShardingAlgorithm<Long> { @Override public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) { // 基于order_id的哈希值计算分片 int tableIndex = Math.abs(shardingValue.getValue().hashCode()) % availableTargetNames.size(); return availableTargetNames.stream() .filter(name -> name.endsWith("_" + tableIndex)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("无法找到匹配的表")); } } ``` --- ### 3. 配置Sharding-JDBC和MyBatis-Plus (`application.yml`) ```yaml spring: shardingsphere: datasource: names: ds0 ds0: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/sharding_db?useSSL=false username: root password: root rules: sharding: tables: t_order: # 逻辑表名 actual-data-nodes: ds0.order_$->{0..1} # 物理表order_0和order_1 table-strategy: standard: sharding-column: order_id sharding-algorithm-name: custom-hash sharding-algorithms: custom-hash: type: CLASS_BASED props: strategy: STANDARD algorithm-class: com.example.sharding.algorithm.CustomHashShardingAlgorithm props: sql-show: true # MyBatis-Plus配置 mybatis-plus: configuration: map-underscore-to-camel-case: true global-config: db-config: id-type: INPUT # 使用自定义ID,Sharding-JDBC需明确分片键值 type-aliases-package: com.example.sharding.model ``` --- ### 4. 创建数据库表 ```sql -- order_0 表 CREATE TABLE order_0 ( order_id BIGINT PRIMARY KEY COMMENT '分片键', user_id INT NOT NULL, product_name VARCHAR(100), price DECIMAL(10,2), create_time DATETIME ); -- order_1 表 (结构相同) CREATE TABLE order_1 ( order_id BIGINT PRIMARY KEY, user_id INT NOT NULL, product_name VARCHAR(100), price DECIMAL(10,2), create_time DATETIME ); ``` --- ### 5. 实体类与Mapper ```java // 订单实体 (Order.java) @Data @TableName("t_order") // 逻辑表名 public class Order { private Long orderId; // 分片键 private Integer userId; private String productName; private BigDecimal price; private Date createTime; } ``` ```java // Mapper接口 (OrderMapper.java) public interface OrderMapper extends BaseMapper<Order> { } ``` --- ### 6. 新增数据接口 ```java // Service实现 (OrderService.java) @Service @RequiredArgsConstructor public class OrderService { private final OrderMapper orderMapper; public void createOrder(Order order) { // 使用MyBatis-Plus的insert方法 orderMapper.insert(order); } } ``` ```java // Controller (OrderController.java) @RestController @RequestMapping("/orders") @RequiredArgsConstructor public class OrderController { private final OrderService orderService; @PostMapping public ApiResponse createOrder(@RequestBody Order order) { orderService.createOrder(order); return ApiResponse.success("订单创建成功"); } } ``` --- ### 7. 测试验证 使用Postman发送请求: ```http POST http://localhost:8080/orders Content-Type: application/json { "orderId": 123456789, "userId": 1001, "productName": "智能手机", "price": 5999.00, "createTime": "2023-10-15T14:30:00" } ``` 控制台日志将显示实际插入的表名: ```log ShardingSphere-SQL: Actual SQL: ds0 ::: INSERT INTO order_1 (order_id, ...) ``` --- ### 关键技术说明 1. **分片策略**:自定义哈希算法确保数据均匀分布在$N$张表中,公式:$ \text{tableIndex} = |\text{hash(orderId)}| \mod N $ 2. **逻辑表映射**:MyBatis-Plus的`@TableName("t_order")`对应Sharding-JDBC配置的逻辑表 3. **ID生成策略**:需显式设置分片键值,避免MyBatis-Plus自动生成ID造成分片路由错误[^1] 4. **物理表创建**:需手动创建`order_0`和`order_1`物理表,表结构保持一致 > **注意**:避免在未指定分片键的条件下进行全表查询,否则会触发**广播查询**导致性能下降[^1] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值