terrymanu commented on issue #35077:
URL:
https://github.com/apache/shardingsphere/issues/35077#issuecomment-3502893596
Problem Understanding
I understand you're experiencing a validation issue after upgrading from
ShardingSphere Spring Boot Starter 4.1.1 to ShardingSphere JDBC 5.5.1. Your
setup supports both partitioned and non-partitioned databases using
common data objects, and the virtual field partition_date in your data
object is causing validation failures before your sharding algorithm can
execute.
Root Cause Analysis
This is a configuration validation enhancement in ShardingSphere 5.5.1,
not a bug. The core issue is:
1. Virtual Field Mapping: Your getPartitionDate() method creates a virtual
field that doesn't exist in actual database tables
2. Pre-execution Validation: ShardingSphere 5.5.1 performs stricter table
structure validation before executing routing logic
3. First Node Validation: ShardingSphere uses the first node in
actualDataNodes for initial table metadata validation
Recommended Solutions
Solution 1: Mark Virtual Field with @Transient (Recommended)
Modify your data object to exclude the virtual field from database mapping:
```java
@Data
@Alias("req_unique")
@Getter
@Setter
public class RequestUniqueDO {
private String requestId;
private String orderId;
/**
* This method is used for partitioning logic and should not be mapped
to any database column.
* It's used by the sharding algorithm to determine the correct
database and table.
*/
@Transient // Add this annotation to exclude from database mapping
public Date getPartitionDate() {
return Utils.composePartitionDate(this.orderId);
}
// Override the setter to prevent any database mapping
public void setPartitionDate(Date partitionDate) {
// No-op - this is a computed field
}
}
```
Solution 2: Alternative Using Different Data Objects
Consider using separate data objects for partitioned and non-partitioned
tables:
```java
// For non-partitioned tables
@Data
@Alias("req_unique")
public class RequestUniqueDO {
private String requestId;
private String orderId;
}
// For partitioned tables
@Data
@Alias("req_unique")
public class PartitionedRequestUniqueDO extends RequestUniqueDO {
public Date getPartitionDate() {
return Utils.composePartitionDate(this.orderId);
}
}
```
Solution 3: Optimize Configuration Order
If you cannot modify the data objects, adjust your actualDataNodes based
on your primary use case:
```yaml
rules:
- !SHARDING
tables:
req_unique:
# Order nodes based on your primary query pattern
actualDataNodes:
db$->{0..1}.req_unique_$->{0..2},dbp$->{0..1}.req_unique_$->{0..1}
databaseStrategy:
hint:
shardingAlgorithmName: db_complex_sharding_algorithm
```
Additional Recommendations
Improve Your Sharding Algorithm
Enhance your DBComplexShardingAlgorithm to handle validation more
gracefully:
```java
public class DBComplexShardingAlgorithm implements
HintShardingAlgorithm<String> {
@Override
public Collection<String> doSharding(Collection<String>
availableTargets,
HintShardingValue<String>
hintShardingValue) {
List<String> shardingResult = new ArrayList<>();
Collection<String> values = hintShardingValue.getValues();
if (values.isEmpty()) {
return availableTargets;
}
String orderId = values.iterator().next();
// Add null check and validation
if (orderId == null || orderId.isEmpty()) {
return availableTargets;
}
String targetDb;
if (isPartitionedRequired(orderId)) {
targetDb = getPartitionedShard(orderId);
} else {
targetDb = getNonPartitionedShard(orderId);
}
// Verify target exists in available targets
if (availableTargets.contains(targetDb)) {
shardingResult.add(targetDb);
}
return shardingResult;
}
private boolean isPartitionedRequired(String orderId) {
// Implement your business logic to determine if partitioning is
needed
return PARTITIONED_ENABLED && shouldUsePartitioning(orderId);
}
}
```
Request for Additional Information
If the solutions above don't resolve your issue, please provide:
1. Complete ShardingSphere configuration (including datasource
configuration)
2. Database table schemas (DDL statements for both partitioned and
non-partitioned tables)
3. Full stack trace of the exception
4. Example SQL statements that are failing
5. Spring Boot version and Java version being used
Summary
The issue is caused by enhanced validation in ShardingSphere 5.5.1 that
checks data object fields against table metadata before routing. The
recommended solution is to use @Transient annotation to mark virtual fields,
which is the standard approach in JPA/Spring applications and follows
ShardingSphere best practices.
This maintains backward compatibility while providing cleaner separation
between business logic fields and database mapping fields.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]