问题描述
这是我的实体
@Table("amazon_rds_inventory")
public class AmazonDBInstanceDataSelect {
@Id
@Column("id")
private long id;
@Column("inventory_Metadata")
private String inventoryMetadata;
@Column("aws_identifier")
private String awsIdentifier;
@Column("host")
private String host;
@Column("region")
private String region;
@Column("type")
private AmazonInventoryType amazonInventoryType;
@Column("created_by")
private String user;
@Column("created_on")
private Timestamp createdOn;
@Column("cloned")
private boolean cloned;
@Column("inventory_Metadata->>'$.dbclusterIdentifier' as clusterIdentifier")
private String clusterIdentifier;
@Column("deleted")
private boolean deleted;
}
“inventory_Metadata”列的json数据
{
"port": 27017,"engine": "docdb","status": "available","multiAZ": false,"tagList": [],"capacity": null,"endpoint": "nimesa-docdb-cluster-01.cluster-cjzyjmw4obtv.us-east-1.docdb.amazonaws.com","kmsKeyId": "arn:aws:kms:us-east-1:220709770714:key/293f9b17-43fc-4946-92d6-cfcb9965a8cd","engineMode": "provisioned","cloneGroupId": null,"databaseName": null,"dbclusterarn": "arn:aws:rds:us-east-1:220709770714:cluster:nimesa-docdb-cluster-01","hostedZoneId": "ZNKXH85TT8WVW","dbsubnetGroup": "custom-subnetgroupwith-custom","engineVersion": "4.0.0","masterUsername": "nimesa","readerEndpoint": "nimesa-docdb-cluster-01.cluster-ro-cjzyjmw4obtv.us-east-1.docdb.amazonaws.com","associatedRoles": [],"backtrackWindow": null,"customEndpoints": [],"percentProgress": null,"allocatedStorage": 1,"characterSetName": null,"dbclusterMembers": [
{
"clusterWriter": true,"promotionTier": 1,"isClusterWriter": true,"dbinstanceIdentifier": "nimesa-docdb-01","dbclusterParameterGroupStatus": "in-sync"
}
],"storageEncrypted": true,"availabilityZones": [
"us-east-1f","us-east-1b","us-east-1a"
],"clusterCreateTime": 1615532359067,"crossAccountClone": false,"domainMemberships": [],"vpcSecurityGroups": [
{
"status": "active","vpcSecurityGroupId": "sg-05c8ed6d9836007fd"
}
],"activityStreamMode": null,"copyTagsToSnapshot": false,"deletionProtection": false,"dbClusterResourceId": "cluster-6OQQJU32K2ZZE2GSTHP2DHNGZM","dbclusterIdentifier": "nimesa-docdb-cluster-01","httpEndpointEnabled": false,"activityStreamStatus": "stopped","latestRestorableTime": 1620666452774,"backupRetentionPeriod": 1,"earliestBacktrackTime": null,"pendingModifiedValues": null,"preferredBackupWindow": "00:00-00:30","activityStreamKmsKeyId": null,"earliestRestorableTime": 1620666452774,"readReplicaIdentifiers": [],"dbclusterParameterGroup": "default.docdb4.0","scalingConfigurationInfo": null,"preferredMaintenanceWindow": "wed:07:48-wed:08:18","globalWriteForwardingStatus": null,"replicationSourceIdentifier": null,"enabledCloudwatchLogsExports": [],"backtrackConsumedChangeRecords": null,"globalWriteForwardingRequested": null,"activityStreamKinesisstreamName": null,"dbclusterOptionGroupMemberships": [],"iamdatabaseAuthenticationEnabled": false
}
我得到的错误:- java.sql.sqlSyntaxErrorException: 未知列 'amazon_rds_inventory.inventory_Metadata->>'$.dbclusterIdentifier' as clusterIdentifier' in 'field list'
我想获取 json 中 dbclusterIdentifier 键的值并将其映射到我的实体
解决方法
根据具体目标,您有多种选择。
让我们从为什么当前的方法行不通开始。
-
@Column
指定一列,而不是任意表达式。正如您所指出的,将其设置为表达式只会产生一个非常奇怪的列名。 - 即使它可以处理表达式,它也不仅需要一个表达式来提取值,还需要一个用于写回值的表达式。
- 该字段仅包含文档的一部分。如果可行,写回该值会将原始 JSON 文档替换为仅包含该值的文档。
让我们看看几个解决方案:
-
在您当前的设置中,您已经将完整的 JSON 文档加载为
inventoryMetadata
。因此,我建议在加载后对实体进行后期处理。在您的应用程序上下文中注册一个AfterLoadCallback
,它将所需的值从inventoryMetadata
提取到clusterIdentifier
-
如果您真的想以结构化方式访问 JSON 文档,您可以使用自定义类型,例如
InventoryMetadata
并注册转换器以将其转换为String
并返回,如果我记得正确应该适用于 SQL 标准,所以希望它适用于 MySQL。 -
如果您想将 JSON 处理排除在 Java 代码之外,您可以在数据库中有一个数据库视图并在那里进行任何提取/操作。您可以将您的实体映射到该视图。如果视图是可更新的,您甚至可以使用 if 来写回数据。
-
您描述的使用专用
@Query
的解决方案是另一种选择,当您只想读取数据时,它可以正常工作。