I'm setting up a table in Postgres, and want to map List to jdbc array type using custom #Converter class. But I
get org.hibernate.MappingException: No Dialect mapping for JDBC type: 984991021
//StoredJob class for creating table:
#Entity
#Table(name = "jobs")
public class StoredJob {
....
//The error is here
#Column
#Convert(converter = JobFileListConverter.class)
private List<UUID> jobFiles;
//Converter class:
#Converter
public class JobFileListConverter implements
AttributeConverter<List<UUID>, UUID[]> {
#Override
public UUID[] convertToDatabaseColumn(List<UUID> uuidList) {
return uuidList.toArray(UUID[]::new);
}
#Override
public List<UUID> convertToEntityAttribute(UUID[] uuidArray) {
return Arrays.asList(uuidArray);
}
Change this:
private List<UUID> jobFiles;
with this one:
private UUID[] jobFiles;
But, I strongly suggest you to remove '#Convert' annotation and add a getter method as below:
public UUID[] getJobFiles() {
return jobFiles.stream().toArray(UUID[]::new);
}
Related
I am trying to write an interface that extends CrudRepository that will return a list of a particular field. When I use that method, I get ConverterNotFoundException. I have two questions:
Is there a specific Spring Boot query if I want a list containing a specific field?
Am I implementing the converter correctly? I am not sure how to call WebConfig.
// EmployeeRepository.java
#Repository
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
List<String> findByEmployeeId(String employeeId); // ConverterNotFoundException. Expecting list of employee's full name
}
// EmployeeToStringConverter.java
#Component
public class EmployeeToStringConverter implements Converter<Employee, String> {
#Override
public String convert(Employee source) {
return source.getFullName();
}
}
// WebConfig.java
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new EmployeeToStringConverter());
}
}
// Employee.java
#Entity
#Data
#NoArgsConstructor
#Getter
#Table(name = "employees")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="Id")
private Long id;
#Column(name="FullName")
private String fullName;
#Column(name="NickName")
private String nickName;
public HubKey(String fullName, String nickName) {
this.fullName = fullName;
this.nickName = nickName;
}
}
// Exception when calling EmployeeRepository.findByEmployeeId()
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [com.jon.demo.domain.entity.Employee] to type [java.lang.String]
The converter you have registered in the WebMvcConfigurer is used for formatting data in the view(The view in MVC).
You should add converter to Spring Data related custom conversions beans, every Spring Data sub project has its own registration entry there.
Please read the Spring Data related docs.
I have a table with a string attribute that is my hask key and another attribute that is of type list, but when doing some operation whose query goes through this list an error is returned that the list object must have the #DynamoDBTable annotation but the object is not a table.
Error: "com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException: class com.beasu.appbeasu.adapter.db.entity.ParesEntity not annotated with #DynamoDBTable
Look:
#DynamoDBTable(tableName = "tb_01_pare")
#ToString
#EqualsAndHashCode
public class DataPareEntity {
private String codDist;
private List<PareEntity> pares;
#DynamoDBHashKey(attributeName = "cod_dist")
public String getCodDist() {
return codDist;
}
public void setCodDist(String codDist) {
this.codDist= codDist;
}
#DynamoDBAttribute(attributeName= "obt_lis_pares")
public List<ParesEntity> getPares() {
return pares;
}
public void setPares(List<PareceresEntity> pareceres) {
this.pareceres = pareceres;
}
}
#AllArgsConstructor
#NoArgsConstructor
#DynamoDBDocument
public class ParesEntity {
private String codDist;
private String numFun;
private String txtJus;
private String indDec;
private String dateHr;
} // getters and setters...
If anyone knows the reason for this problem and can let me know I would be very grateful.
I have an Entity that would like to extend it by adding some fields. first of all they are not accessible to me to change directly, they are in their own jar file. here are the base entities:
#Entity
table(name="ACCOUNTDEF")
public class EtAccountDef
{
private String cNumber;
private List<EtAccount> accounts = new ArrayList();
public String getCNumber()
{
return cNumber;
}
public void setCNumber(String cNumber) {
this.cNumber = cNumber;
}
#OneToMany(fetch=FetchType.LAZY, cascade={javax.persistence.CascadeType.ALL}, mappedBy="accountDef")
public List<EtAccount> getAccounts() {
return accounts;
}
public void setAccounts(List<EtAccount> accounts) {
this.accounts = accounts;
}
}
which is the parent class and the below is child class:
#Entity
#Table(name="ACCOUNT")
public class EtAccount
{
private Double accountAmount;
private EtAccountDef accountDef;
private List<EtAccountItems> accountItems = new ArrayList();
#ManyToOne(fetch=FetchType.LAZY)
public EtAccountDef getAccountDef() {
return accountDef;
}
public void setAccountDef(EtAccountDef accountDef) {
this.accountDef = accountDef;
}
#OneToMany(fetch=FetchType.LAZY, cascade={javax.persistence.CascadeType.ALL}, mappedBy="account")
public List<EtAccountItems> getAccountItems() {
return accountItems;
}
public void setAccountItems(List<EtAccountItems> accountItems) {
this.accountItems = accountItems;
}
}
so I tried these changes to achieve my goal.
#MappedSuperclass
public abstract class OtAbstractAccount extends EtAccount {
private Double AccountCommission;
#Column(columnDefinition="decimal(15,2)")
public Double getAccountCommission() {
return accountCommission;
}
public void setAccountCommission(Double accountCommission) {
this.accountCommission = accountCommission;
}
and then extend it by this entity:
#Entity
#Table(name="ACCOUNT")
public class OtCostumAccount extends OtAbstractAccount {
}
The fields are now added to the base table(EtAccount) but
after compiling I get an error in the Weblogic that says:
Caused by: org.hibernate.AnnotationException: #OneToOne or #ManyToOne
on EtAccount.accountDef references an unknown entity: EtAccountDef
I have entered these two line in my ORM file:
<mapped-superclass class="package.OtAbstractAccount" />
<entity class="package.OtCostumAccount" />
Surprisingly when i comment
<mapped-superclass class="package.OtAbstractAccount" />
from ORM the weblogic does not rise any error but when I try to load object another error will be created that say:
Caused by: javax.persistence.PersistenceException:
org.hibernate.exception.SQLGrammarException: ORA-00904:
"OtCostumAccount "."DTYPE": invalid identifier
I'm confused whit these error and I'll appreciate any help.
If you can not modify the parent class, then the default hibernate inheritance strategy apply: one table per class. This strategy require a discriminant column which, by default, is DTYPE. Did you try to add a discriminator column to your OtCostumAccount entity or create the DTYPE column ?
class Identifier {
private long id;
private String type;
private List<Status> statuses;
}
class Customer {
private Identifier identifier;
}
class CustomerProfile {
private Customer customer;
}
class CustomerIdentifierDO {
private long id;
}
class CustomeDO {
private CustomerIdentiferDO custID;
}
class CustomerProfileDO {
private String category;
private List<Status> custStatuses;
private CustomeDO customer;
}
#Mapper
public interface CustomerProfileMapper {
CustomerProfile toCustomerProfile(CustomerProfileDO profileDO) ;
Customer toCustomer(CustomerDO customerDO);
Identifier toIdentifier(CustomerIdentifierDO identifierDO);
}
Everything works fine till this. Now I want to map custStatuses, category of CustomerProfileDO class to statuses and type of Identifier class. I've no idea how to supply CustomerProfileDO object to toIdentifier mapping method, so that I can include the mapping there itself. I tried following
#Mappings({
#Mapping(target = "customer.identifier.type", source = "category")
})
CustomerProfile toCustomerProfile(CustomerProfileDO profileDO) ;
But this nested mapping is overriding all the mapping config of below method. That should not happen.
toIdentifer(CustomerIdentifierDO identifierDO)
Is there any way to achieve this?
Currently MapStruct can pass source parameters to single methods. In order to achieve what you are looking for (without using nested target types you would need to use something like #AfterMapping. It can look like:
#Mapper
public interface CustomerProfileMapper {
CustomerProfile toCustomerProfile(CustomerProfileDO profileDO) ;
Customer toCustomer(CustomerDO customerDO);
Identifier toIdentifier(CustomerIdentifierDO identifierDO);
#AfterMapping
default void afterMapping(#MappingTarget CustomerProfile profile, CustomerProfieDO profileDO) {
Identifier identifier = profile.getCustomer().getIdentifier();
identifier.setStatus(profileDO.setStatus());
identifier.setType(profileDO.setCategory());
}
}
I am trying to access Tuple data structure I have stored in Cassandra with Mapper. But, I am unable to. I haven't found any example online.
This is the table and data I have created.
cqlsh:test> CREATE TABLE test.test_nested (id varchar PRIMARY KEY, address_mapping list<frozen<tuple<text,text>>>);
cqlsh:test> INSERT INTO test.test_nested (id, address_mapping) VALUES ('12345', [('Adress 1', 'pin1'), ('Adress 2', 'pin2')]);
cqlsh:test>
cqlsh:test> select * from test.test_nested;
id | address_mapping
-------+----------------------------------------------
12345 | [('Adress 1', 'pin1'), ('Adress 2', 'pin2')]
(1 rows)
My mapped class(using lombok for builder, getter, setter):
#Builder
#Table(keyspace = "test", name = "test_nested")
public class TestNested {
#PartitionKey
#Column(name = "id")
#Getter
#Setter
private String id;
#Column(name = "address_mapping")
#Frozen
#Getter
#Setter
private List<Object> address_mapping;
}
My Mapper class:
public class TestNestedStore {
private final Mapper<TestNested> mapper;
public TestNestedStore(Mapper<TestNested> mapper) {
this.mapper = mapper;
}
public void insert(TestNested userDropData) {
mapper.save(userDropData);
}
public void remove(String id) {
mapper.delete(id);
}
public TestNested findByUserId(String id) {
return mapper.get(id);
}
public ListenableFuture<TestNested> findByUserIdAsync(String id) {
return mapper.getAsync(id);
}
}
I am trying to access data in a test method as follows:
#Test
public void testConnection2(){
MappingManager manager = new MappingManager(scyllaDBConnector.getSession());
Mapper<TestNested> mapper = manager.mapper(TestNested.class);
TestNestedStore testNestedStore = new TestNestedStore(mapper);
ListenableFuture<TestNested> fut = testNestedStore.findByUserIdAsync("12345");
Futures.addCallback(fut, new FutureCallback<TestNested>() {
#Override
public void onSuccess(TestNested testNested) {
}
#Override
public void onFailure(Throwable throwable) {
System.out.println("Call failed");
}
});
}
Bit, I am unable to access the tuple. I get this error:
java.lang.IllegalArgumentException: Error while checking frozen types on field address_mapping of entity com.example.model.TestNested: expected List to be not frozen but was frozen
at com.datastax.driver.mapping.AnnotationChecks.validateAnnotations(AnnotationChecks.java:73)
at com.datastax.driver.mapping.AnnotationParser.parseEntity(AnnotationParser.java:81)
at com.datastax.driver.mapping.MappingManager.getMapper(MappingManager.java:148)
at com.datastax.driver.mapping.MappingManager.mapper(MappingManager.java:105)
I have also tried with private List<TupleValue> address_mapping;. But of no use!
How do I access Tuple values through object mapper of cassandra?
You define address_mapping as list<frozen<tuple<text,text>>>, that is, a list of frozen tuple values. To communicate this to the MappingManager, you can use the #FrozenValue attribute.
TestNested should look like:
#Builder
#Table(keyspace = "test", name = "test_nested")
public class TestNested {
...
#Column(name = "address_mapping")
#Frozen
#Getter
#Setter
#FrozenValue
private List<Object> address_mapping;
}
For defining the cassandra datatype of
map<text,frozen<tuple<text,text,int,text>>>
in java entity class mention the datatype as,
import com.datastax.driver.core.TupleValue;
#FrozenValue
private Map<String,TupleValue> event_driven;