使用 Spring-data-cassandra 查询具有复合主键的表
Querying Tables with Composite Primary Keys using Spring-data-cassandra
我在使用 CassandraReporitory 的 findOne() 或 findAll() 方法时遇到以下异常:
Caused by: java.lang.IllegalStateException: property does not have a single column mapping
at org.springframework.data.cassandra.mapping.BasicCassandraPersistentProperty.getColumnName(BasicCassandraPersistentProperty.java:134)
at org.springframework.data.cassandra.convert.BasicCassandraRowValueProvider.getPropertyValue(BasicCassandraRowValueProvider.java:64)
at org.springframework.data.cassandra.convert.BasicCassandraRowValueProvider.getPropertyValue(BasicCassandraRowValueProvider.java:35)
at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:78)
at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:71)
at org.springframework.data.convert.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:83)
at org.springframework.data.cassandra.convert.MappingCassandraConverter.readEntityFromRow(MappingCassandraConverter.java:133)
at org.springframework.data.cassandra.convert.MappingCassandraConverter.readRow(MappingCassandraConverter.java:115)
at org.springframework.data.cassandra.convert.MappingCassandraConverter.read(MappingCassandraConverter.java:200)
at org.springframework.data.cassandra.repository.query.AbstractCassandraQuery.getSingleEntity(AbstractCassandraQuery.java:176)
at org.springframework.data.cassandra.repository.query.AbstractCassandraQuery.execute(AbstractCassandraQuery.java:133)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:454)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:432)
我的class定义如下:
@PrimaryKeyClass
public class ItemAndLocationKey implements Serializable {
private static final long serialVersionUID = 1L;
@PrimaryKeyColumn(name = "itemId", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
@CassandraType(type = Name.UUID)
private UUID itemId;
@PrimaryKeyColumn(name = "locationId", ordinal = 1, type = PrimaryKeyType.CLUSTERED)
@CassandraType(type = Name.UUID)
private UUID locationId;
public ItemAndLocationKey(UUID itemId, UUID locationId) {
this.itemId = itemId;
this.locationId = locationId;
}
public UUID getItemId() {
return itemId;
}
public void setItemId(UUID itemId) {
this.itemId = itemId;
}
public UUID getLocationId() {
return locationId;
}
public void setLocationId(UUID locationId) {
this.locationId = locationId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ItemAndLocationKey that = (ItemAndLocationKey) o;
if (!itemId.equals(that.itemId)) return false;
return locationId.equals(that.locationId);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + itemId.hashCode();
result = prime * result + locationId.hashCode();
return result;
}
}
@Table(value = ItemAndLocation.tableName)
public class ItemAndLocation {
@org.springframework.data.annotation.Transient
public static final String tableName = "ItemAndLocation";
@PrimaryKey
private ItemAndLocationKey itemAndLocationKey;
public ItemAndLocation(ItemAndLocationKey itemAndLocationKey) {
this.itemAndLocationKey = itemAndLocationKey;
}
public ItemAndLocationKey getItemAndLocationKey() {
return itemAndLocationKey;
}
public void setItemAndLocationKey(ItemAndLocationKey itemAndLocationKey) {
this.itemAndLocationKey = itemAndLocationKey;
}
}
public interface ItemAndLocationRepository extends TypedIdCassandraRepository<ItemAndLocation, ItemAndLocationKey> {
}
基本上这里发生的事情是,在调用 findOne() 或 findAll() 期间从 Cassandra 读取一行后,spring data cassandra 尝试使用 ClassGeneratingEntityInstantiator 来实例化不知道的 ItemAndLocation 对象如何填充复合主键对象 ItemAndLocationKey。我不知道如何提供自定义对象实例化器。当前版本没有示例或文档。
任何帮助将不胜感激。
我有同样的问题,问题出在用@Table.
注释的class
在您的方案中,您必须删除以下 class 中的重载构造函数:
@Table(value = ItemAndLocation.tableName)
public class ItemAndLocation {
@org.springframework.data.annotation.Transient
public static final String tableName = "ItemAndLocation";
@PrimaryKey
private ItemAndLocationKey itemAndLocationKey;
// \\\\\\\\\\ REMOVE THIS CONSTRUCTOR //////////////////
// public ItemAndLocation(ItemAndLocationKey itemAndLocationKey) {
// this.itemAndLocationKey = itemAndLocationKey;
// }
// ////////////////////////////////\\\\\\\\\\\\\\\\
public ItemAndLocationKey getItemAndLocationKey() {
return itemAndLocationKey;
}
public void setItemAndLocationKey(ItemAndLocationKey itemAndLocationKey) {
this.itemAndLocationKey = itemAndLocationKey;
}
}
希望对您有所帮助:)
我在主实体 class 和 PrimaryKey
-class 中都遇到了同样的问题。为我修复的是提供不带参数的默认构造函数并将所有字段初始化为 some 默认值,这意味着 null
for Object
s, false
对于 boolean
s 和 0
对于所有其他原始类型。
在你的情况下,这意味着 add:
private ItemAndLocation() {
this.itemAndLocationKey = null;
}
和
private ItemAndLocationKey() {
this.itemId = null;
this.locationId = null;
}
构造函数不需要 public
,字段可以final
,框架将通过反射设置值。
我在使用 CassandraReporitory 的 findOne() 或 findAll() 方法时遇到以下异常:
Caused by: java.lang.IllegalStateException: property does not have a single column mapping
at org.springframework.data.cassandra.mapping.BasicCassandraPersistentProperty.getColumnName(BasicCassandraPersistentProperty.java:134)
at org.springframework.data.cassandra.convert.BasicCassandraRowValueProvider.getPropertyValue(BasicCassandraRowValueProvider.java:64)
at org.springframework.data.cassandra.convert.BasicCassandraRowValueProvider.getPropertyValue(BasicCassandraRowValueProvider.java:35)
at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:78)
at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:71)
at org.springframework.data.convert.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:83)
at org.springframework.data.cassandra.convert.MappingCassandraConverter.readEntityFromRow(MappingCassandraConverter.java:133)
at org.springframework.data.cassandra.convert.MappingCassandraConverter.readRow(MappingCassandraConverter.java:115)
at org.springframework.data.cassandra.convert.MappingCassandraConverter.read(MappingCassandraConverter.java:200)
at org.springframework.data.cassandra.repository.query.AbstractCassandraQuery.getSingleEntity(AbstractCassandraQuery.java:176)
at org.springframework.data.cassandra.repository.query.AbstractCassandraQuery.execute(AbstractCassandraQuery.java:133)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:454)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:432)
我的class定义如下:
@PrimaryKeyClass
public class ItemAndLocationKey implements Serializable {
private static final long serialVersionUID = 1L;
@PrimaryKeyColumn(name = "itemId", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
@CassandraType(type = Name.UUID)
private UUID itemId;
@PrimaryKeyColumn(name = "locationId", ordinal = 1, type = PrimaryKeyType.CLUSTERED)
@CassandraType(type = Name.UUID)
private UUID locationId;
public ItemAndLocationKey(UUID itemId, UUID locationId) {
this.itemId = itemId;
this.locationId = locationId;
}
public UUID getItemId() {
return itemId;
}
public void setItemId(UUID itemId) {
this.itemId = itemId;
}
public UUID getLocationId() {
return locationId;
}
public void setLocationId(UUID locationId) {
this.locationId = locationId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ItemAndLocationKey that = (ItemAndLocationKey) o;
if (!itemId.equals(that.itemId)) return false;
return locationId.equals(that.locationId);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + itemId.hashCode();
result = prime * result + locationId.hashCode();
return result;
}
}
@Table(value = ItemAndLocation.tableName)
public class ItemAndLocation {
@org.springframework.data.annotation.Transient
public static final String tableName = "ItemAndLocation";
@PrimaryKey
private ItemAndLocationKey itemAndLocationKey;
public ItemAndLocation(ItemAndLocationKey itemAndLocationKey) {
this.itemAndLocationKey = itemAndLocationKey;
}
public ItemAndLocationKey getItemAndLocationKey() {
return itemAndLocationKey;
}
public void setItemAndLocationKey(ItemAndLocationKey itemAndLocationKey) {
this.itemAndLocationKey = itemAndLocationKey;
}
}
public interface ItemAndLocationRepository extends TypedIdCassandraRepository<ItemAndLocation, ItemAndLocationKey> {
}
基本上这里发生的事情是,在调用 findOne() 或 findAll() 期间从 Cassandra 读取一行后,spring data cassandra 尝试使用 ClassGeneratingEntityInstantiator 来实例化不知道的 ItemAndLocation 对象如何填充复合主键对象 ItemAndLocationKey。我不知道如何提供自定义对象实例化器。当前版本没有示例或文档。
任何帮助将不胜感激。
我有同样的问题,问题出在用@Table.
注释的class在您的方案中,您必须删除以下 class 中的重载构造函数:
@Table(value = ItemAndLocation.tableName)
public class ItemAndLocation {
@org.springframework.data.annotation.Transient
public static final String tableName = "ItemAndLocation";
@PrimaryKey
private ItemAndLocationKey itemAndLocationKey;
// \\\\\\\\\\ REMOVE THIS CONSTRUCTOR //////////////////
// public ItemAndLocation(ItemAndLocationKey itemAndLocationKey) {
// this.itemAndLocationKey = itemAndLocationKey;
// }
// ////////////////////////////////\\\\\\\\\\\\\\\\
public ItemAndLocationKey getItemAndLocationKey() {
return itemAndLocationKey;
}
public void setItemAndLocationKey(ItemAndLocationKey itemAndLocationKey) {
this.itemAndLocationKey = itemAndLocationKey;
}
}
希望对您有所帮助:)
我在主实体 class 和 PrimaryKey
-class 中都遇到了同样的问题。为我修复的是提供不带参数的默认构造函数并将所有字段初始化为 some 默认值,这意味着 null
for Object
s, false
对于 boolean
s 和 0
对于所有其他原始类型。
在你的情况下,这意味着 add:
private ItemAndLocation() {
this.itemAndLocationKey = null;
}
和
private ItemAndLocationKey() {
this.itemId = null;
this.locationId = null;
}
构造函数不需要 public
,字段可以final
,框架将通过反射设置值。