Codec not found for requested operation: [list<varchar> <-> java.nio.HeapByteBuffer] - ignite

I am having an issue with storing data to Cassandra table from apache ignite when I am trying to insert into a column of list data type in Cassandra
Cassandra table:
CREATE TABLE business_categories (
id int,
category_name TEXT,
sub_categories list<TEXT>,
PRIMARY KEY(category_name, id)
);
xml file:
<persistence keyspace="ignite" table="business_categories">
<keyspaceOptions>
REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 1}
AND DURABLE_WRITES = true
</keyspaceOptions>
<tableOption>
comment = 'Cache test'
AND read_repair_chance = 0.2
</tableOption>
<keyPersistence class="com.cache.business.model.BusinessCategoriesKey" strategy="POJO"/>
<valuePersistence class="com.cache.business.model.BusinessCategoriesValue" strategy="POJO"/>
</persistence>
key class object:
public class BusinessCategoriesKey implements Serializable {
private static final long serialVersionUID = 581472167344584014L;
private int id;
private String category_name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCategory_name() {
return category_name;
}
public void setCategory_name(String category_name) {
this.category_name = category_name;
}
}
value class object:
public class BusinessCategoriesValue implements Serializable {
private static final long serialVersionUID = -1694694702874919854L;
private List<String> sub_categories = new ArrayList<>();
public List<String> getSub_categories() {
return sub_categories;
}
public void setSub_categories(List<String> sub_categories) {
this.sub_categories = sub_categories;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
I am getting the below error message
Caused by: com.datastax.driver.core.exceptions.CodecNotFoundException: Codec not found for requested operation: [list <-> java.nio.HeapByteBuffer]

The sub_categories field is a java.util.List and it seems Apache Ignite does not provide a direct mapping to appropriate Cassandra type for such kind of Java types.
So, this field could be persisted into Cassandra only if you manually specify all mapping details for the object type and if field type itself is implementing java.io.Serializable interface.
In such case, the field will be persisted into a separate table column as a blob.
Please try to modify your code in the following way:
CREATE TABLE business_categories (
id int,
category_name text
sub_categories blob,
PRIMARY KEY(category_name, id)
);
Persistence descriptor:
<persistence keyspace="ignite" table="business_categories">
<keyspaceOptions>
REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 1}
AND DURABLE_WRITES = true
</keyspaceOptions>
<tableOption>
comment = 'Cache test'
AND read_repair_chance = 0.2
</tableOption>
<keyPersistence class="com.cache.business.model.BusinessCategoriesKey" strategy="POJO"/>
<valuePersistence class="com.cache.business.model.BusinessCategoriesValue"
strategy="POJO"
serializer="org.apache.ignite.cache.store.cassandra.serializer.JavaSerializer">
<field name="sub_categories" column="sub_categories"/>
</valuePersistence>
You can find additional details here: Cassandra Integration Examples

Related

Android room compiler error when trying to return a list of own objects in the DAO: incompatible types: <null> cannot be converted to int

I am using room for database operations. I have a class TableQuestion which holds a string and a id and I have a class TableAnswer which holds a string, an id plus the id of the question where it is refering to. QuizTask brings together the Question with all its answers. The query getQuestionsWithAnswer should return a QuizTask which wraps the question with all its answers. The error metioned in the title happens in auto-generated code of room.
The relevant part of the interface:
#android.arch.persistence.room.Dao
public interface dbDao {
#Transaction
#Query("SELECT table_question.question, table_answer.answer FROM table_question, table_answer WHERE table_question.id = table_answer.id_question")
LiveData<List<QuizTask>> getQuestionsWithAnswers();
}
Class TableQuestion:
#Entity(foreignKeys = #ForeignKey(entity = TableQuestionnaire.class,
parentColumns = "id",
childColumns = "id_questionnaire",
onDelete = CASCADE),
tableName = "table_question")
public class TableQuestion {
#PrimaryKey
public final int id;
#NonNull
public String question;
#NonNull
public int id_questionnaire;
public String subject;
public String category;
public String sub_category;
#Ignore
public String questionnaire;
public TableQuestion(int id, #NonNull String question, int id_questionnaire, String subject, String category, String sub_category) {
this.id = id;
this.question = question;
this.id_questionnaire = id_questionnaire;
this.questionnaire = null;
this.subject = subject;
this.category = category;
this.sub_category = sub_category;
}
public void setQuestionnaire(String questionnaire){
this.questionnaire = questionnaire;
}
}
Class TableAnswer:
#Entity(foreignKeys = #ForeignKey(entity = TableQuestion.class,
parentColumns = "id",
childColumns = "id_question",
onDelete = CASCADE),
tableName = "table_answer")
public class TableAnswer {
#PrimaryKey
public final int id;
#NonNull
public String answer;
#NonNull
public final int id_question;
public boolean rightAnswer;
public TableAnswer(int id, String answer, int id_question, boolean rightAnswer) {
this.id = id;
this.answer = answer;
this.id_question = id_question;
this.rightAnswer = rightAnswer;
}
}
Class QuizTask:
public class QuizTask {
#Embedded
private TableQuestion question;
#Relation(parentColumn = "id", entityColumn = "id_question")
private List<TableAnswer> answers;
public void setQuestion(TableQuestion question){ this.question = question; }
public TableQuestion getQuestion(){
return question;
}
public void setAnswers(List<TableAnswer> answers) { this.answers = answers; }
public List<TableAnswer> getAnswers() {
return answers;
}
}
AndroidStudio doesn't show any error upon compilation. When room auto-generates the code for getQuestionWithAnswers it shows a compiler error "incompatible types: cannot be converted to int". In the auto-generated dbDao_Impl.java is a row where a TableQuestion object is tried to create but with null for the id parameter. That's where the error occurs. What do I have to change?
I found the issue:
#Query("SELECT table_question.question, table_answer.answer FROM table_question, table_answer WHERE table_question.id = table_answer.id_question")
There is no id selected but used later on. That's why room tries to create objects with Id = null which is not possible. So simply change to:
#Query("SELECT * FROM table_question, table_answer WHERE table_question.id = table_answer.id_question")

OrmLite Foreign Collection to List

I try to use foreign collections in ORMLite. However, I dont know how to convert it into list. I try to do something like this :
public class Car implements Serializable {
#DatabaseField(columnName = "carId" , generatedId = true, id=true)
private int id;
#DatabaseField(columnName = "carNumber")
private String mNumber;
#DatabaseField(columnName = "carName")
private String mName;
#ForeignCollectionField(eager = true,columnName = "carParts")
private Collection<Part> mParts;
ArrayList<Part> parts = new ArrayList<>(mParts);
public ArrayList<Part> getParts() {
return parts;
}
public void setParts(ArrayList<Part> parts) {
this.parts = parts;
}
but when I try to use it I get exception :
java.lang.NullPointerException: collection == null
at this line :
ArrayList<Part> parts = new ArrayList<>(mParts);
please, help.
The reason is simple - you have to wait until mParts will be initialized by ORMLite library, then you can create ArrayList from it.
public ArrayList<Part> getParts() {
return new ArrayList<>( mParts );
}

How to retrieve mongodb field value stored as array of string into a java ArrayList

Document structure is:
db.lookupdata.insert({ parent_key : "category" , key : "accessories" , value : ["belts","cases","gloves","hair","hats","scarves","sunglasses","ties","wallets","watches"]})
i want to store array filed values in java array list
i am finding the document like this:
FindIterable<Document> iterable1 = docCollectionLookup.find(Filters.eq("parent_key", "category"));
Iterator<Document> iter1=iterable1.iterator();
while(iter1.hasNext())
{
Document theObj = iter1.next();
categotyLookUpMap.put(theObj.getString("key"), list);
}
now here how can i retrieve array field values(key:"value") in ArrayList
You can retrieve array field values(key:"value") in ArrayList just like how you retrieve string field key. Please refer below:
FindIterable<Document> iterable1 = docCollectionLookup.find(Filters.eq("parent_key", "category"));
Iterator<Document> iter1=iterable1.iterator();
//Create a HashMap variable with type <String,ArrayList>,according to your needs
Map<String,ArrayList> categotyLookUpMap = new HashMap<String,ArrayList>();
while(iter1.hasNext())
{
Document theObj = iter1.next();
//Get method of Document class will return object,parse it to ArrayList
categotyLookUpMap.put(theObj.getString("key"), (ArrayList)theObj.get("value"));
}
Alternatively, you can use Morphia which is MongoDB object-document mapper in Java. You can setup dependency / download JAR from here
First, create LookupData class to map to lookupdata collection. Annotation #Id is required else will throw exception with message "No field is annotated with #Id; but it is required". So create an _id field for it.
#Entity("lookupdata")
public class LookupData {
#Id
String _id ;
#Property("parent_key")
String parentKey;
String key;
ArrayList<String> value;
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public String getParentKey() {
return parentKey;
}
public void setParentKey(String parentKey) {
this.parentKey = parentKey;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public void setValue(ArrayList<String> value) {
this.value = value;
}
public ArrayList<String> getValue() {
return value;
}
}
Retrieve array field values as below:
MongoClient mongoClient = new MongoClient(new MongoClientURI("mongodb://localhost"));
Morphia morphia = new Morphia();
morphia.map(LookupData.class);
//lookupdata collection is under my local db "tutorials" in this case
Datastore datastore = morphia.createDatastore(mongoClient, "tutorials");
Map<String,ArrayList> categotyLookUpMap = new HashMap<String,ArrayList>();
LookupData lookupData = datastore.find(LookupData.class).get();
categotyLookUpMap.put(lookupData.getKey(), lookupData.getValue());

#ManyToMany mapping in JPA throws Exception [EclipseLink-6076]

I have developed simple JPA2.1 application with Oracle 11g database using Eclipse 2.5.2. Following is my scenario - there are two entities with #ManyToMany relation
Club
People
Club.java
#Entity(name = "CLUB")
public class Club {
#Id
private int c_id;
private String c_name;
#ManyToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE},
fetch=FetchType.EAGER)
#JoinTable(name = "CLUB_PEOPLE",
joinColumns=#JoinColumn(name="c_id", referencedColumnName="c_id"),
inverseJoinColumns=#JoinColumn(name="p_id"))
private Set<People> people=new HashSet<People>();
public int getC_id() {
return c_id;
}
public void setC_id(int c_id) {
this.c_id = c_id;
}
public String getC_name() {
return c_name;
}
public void setC_name(String c_name) {
this.c_name = c_name;
}
public Set<People> getPeople() {
return people;
}
public void setPeople(Set<People> people) {
this.people = people;
}
public void addPeople(People p){
getPeople().add(p);
}
}
People.Java
#Entity(name="people")
public class People{
#Id
private int p_id;
private String name ;
#ManyToMany(mappedBy="people")
private Set<Club> club;
public int getP_id() {
return p_id;
}
public void setP_id(int p_id) {
this.p_id = p_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Client.java
public class Client1 {
public static void main(String[] args) {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("JPA-Query");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Club> cq = cb.createQuery(Club.class).distinct(true);
Root<Club> root = cq.from(Club.class);
final List<Predicate> requiredCriteria = new ArrayList<Predicate>();
final Join people = root.join("people", JoinType.LEFT);
requiredCriteria.add(cb.or(cb.isNull(people)));
requiredCriteria.add(cb.isNull(people.get("name")));
requiredCriteria.add(cb.equal(people.get("name"), "people1"));
TypedQuery<Club> q = em.createQuery(
cq.where(cb.or(requiredCriteria
.toArray(new Predicate[requiredCriteria.size()])
))
);
List<Club> allemps = q.getResultList();
em.close();
emf.close();
}
}
Tables -
CREATE TABLE Club(
c_id number NOT NULL,
c_name VARCHAR2(20)
)
ALTER TABLE Club ADD CONSTRAINT CLUGGRPPK PRIMARY KEY (c_id);
CREATE TABLE People(
p_id number NOT NULL,
name VARCHAR2(20)
)
ALTER TABLE People ADD CONSTRAINT PEOPLEGRPPK PRIMARY KEY (p_id);
CREATE TABLE CLUB_PEOPLE
(
C_ID number,
P_ID number,
CONSTRAINT CLUB_PEOPLEPK PRIMARY KEY (C_ID, P_ID),
CONSTRAINT GROUP_FK FOREIGN KEY("C_ID")
REFERENCES "CLUB"("C_ID") ON DELETE CASCADE,
CONSTRAINT PEOPLE_FK FOREIGN KEY("P_ID")
REFERENCES "PEOPLE"("P_ID") ON DELETE CASCADE
)
When I run my Client.java it throws following exception
Exception Description: Object comparisons can only be used with OneToOneMappings. Other mapping comparisons must be done through query keys or direct attribute level comparisons.
Mapping: [org.eclipse.persistence.mappings.ManyToManyMapping[people]]
Expression: [
Query Key people
Base ManyToMany.Club]
Query: ReadAllQuery(referenceClass=Club )
javax.persistence.PersistenceException: Exception [EclipseLink-6076] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.QueryException
Exception Description: Object comparisons can only be used with OneToOneMappings. Other mapping comparisons must be done through query keys or direct attribute level comparisons.
Mapping: [org.eclipse.persistence.mappings.ManyToManyMapping[people]]
Expression: [
Query Key people
Base ManyToMany.Club]
Query: ReadAllQuery(referenceClass=Club )
at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:480)
at ManyToMany.Client.main(Client.java:75)
Caused by: Exception [EclipseLink-6076] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.QueryException
Exception Description: Object comparisons can only be used with OneToOneMappings. Other mapping comparisons must be done through query keys or direct attribute level comparisons.
Mapping: [org.eclipse.persistence.mappings.ManyToManyMapping[people]]
Expression: [
Query Key people
Base ManyToMany.Club]
Query: ReadAllQuery(referenceClass=Club )
at org.eclipse.persistence.exceptions.QueryException.unsupportedMappingForObjectComparison(QueryException.java:1170)
Please help me to solve above issue. Thanks in advance.

How to rename a component column that is a foreign key?

We are using fluentnhibernate with automapping and we have a naming convention that all columns that are foreign keys, there column name will end with "Key". So we have a convention that looks like this:
public class ForeignKeyColumnNameConvention : IReferenceConvention
{
public void Apply ( IManyToOneInstance instance )
{
// name the key field
string propertyName = instance.Property.Name;
instance.Column ( propertyName + "Key" );
}
}
This works great until we created a component in which one of its values is a foreign key. By renaming the column here it overrides the default name given to the component column which includes the ComponentPrefix which is defined in the AutomappingConfiguration. Is there a way for me to get the ComponentPrefix in this convention? or is there some other way for me to get the column name for components with a property that is a foreign key to end in the word "Key"?
After a lot of fiddling and trial & error (thus being tempted to use your solution with Reflection) I came up with the following:
This method depends on the order of the execution of the conventions. This convention-order happens via a strict hierarchy. In this example, at first, the convention of the component (IDynamicComponentConvention) is being handled and after that the conventions of the inner properties are being handled such as the References mapping (IReferenceConvention).
The strict order is where we make our strike:
We assemble the correct name of the column in the call to Apply(IDynamicComponentConvention instance), put it on the queue. Note that a Queue<T> is used which is a FIFO (first-in-first-out) collection type thus it keeps the order correctly.
Almost immediately after that, Apply(IManyToOneInstanceinstance) is called. We check if there is anything in the queue. If there is, we take it out of the queue and set it as column name. Note that you should not use Peek() instead of Dequeue() as it does not remove the object from the queue.
The code is as follows:
public sealed class CustomNamingConvention : IDynamicComponentConvention, IReferenceConvention {
private static Queue<string> ColumnNames = new Queue<string>();
public void Apply(IDynamicComponentInstance instance) {
foreach (var referenceInspector in instance.References) {
// All the information we need is right here
// But only to inspect, no editing yet :(
// Don't worry, just assemble the name and enqueue it
var name = string.Format("{0}_{1}",
instance.Name,
referenceInspector.Columns.Single().Name);
ColumnNames.Enqueue(name);
}
}
public void Apply(IManyToOneInstance instance) {
if (!ColumnNames.Any())
// Nothing in the queue? Just return then (^_^)
return;
// Set the retrieved string as the column name
var columnName = ColumnNames.Dequeue();
instance.Column(columnName);
// Pick a beer and celebrate the correct naming!
}
}
I Have figured out a way to do this using reflection to get to the underlying mapping of the IManyToOneInspector exposed by the IComponentInstance but was hoping there was a better way to do this?
Here is some example code of how I achieved this:
#region IConvention<IComponentInspector, IComponentInstance> Members
public void Apply(IComponentInstance instance)
{
foreach (var manyToOneInspector in instance.References)
{
var referenceName = string.Format("{0}_{1}_{2}{3}", instance.EntityType.Name, manyToOneInspector.Property.PropertyType.Name, _autoMappingConfiguration.GetComponentColumnPrefix(instance.Property), manyToOneInspector.Property.Name);
if(manyToOneInspector.Property.PropertyType.IsSubclassOf(typeof(LookupBase)))
{
referenceName += "Lkp";
}
manyToOneInspector.Index ( string.Format ( "{0}_FK_IDX", referenceName ) );
}
}
#endregion
public static class ManyToOneInspectorExtensions
{
public static ManyToOneMapping GetMapping(this IManyToOneInspector manyToOneInspector)
{
var fieldInfo = manyToOneInspector.GetType ().GetField( "mapping", BindingFlags.NonPublic | BindingFlags.Instance );
if (fieldInfo != null)
{
var manyToOneMapping = fieldInfo.GetValue( manyToOneInspector ) as ManyToOneMapping;
return manyToOneMapping;
}
return null;
}
public static void Index(this IManyToOneInspector manyToOneInspector, string indexName)
{
var mapping = manyToOneInspector.GetMapping ();
mapping.Index ( indexName );
}
public static void Column(this IManyToOneInspector manyToOneInspector, string columnName)
{
var mapping = manyToOneInspector.GetMapping ();
mapping.Column ( columnName );
}
public static void ForeignKey(this IManyToOneInspector manyToOneInspector, string foreignKeyName)
{
var mapping = manyToOneInspector.GetMapping();
mapping.ForeignKey ( foreignKeyName );
}
}
public static class ManyToOneMappingExtensions
{
public static void Index (this ManyToOneMapping manyToOneMapping, string indexName)
{
if (manyToOneMapping.Columns.First().IsSpecified("Index"))
return;
foreach (var column in manyToOneMapping.Columns)
{
column.Index = indexName;
}
}
public static void Column(this ManyToOneMapping manyToOneMapping, string columnName)
{
if (manyToOneMapping.Columns.UserDefined.Count() > 0)
return;
var originalColumn = manyToOneMapping.Columns.FirstOrDefault();
var column = originalColumn == null ? new ColumnMapping() : originalColumn.Clone();
column.Name = columnName;
manyToOneMapping.ClearColumns();
manyToOneMapping.AddColumn(column);
}
public static void ForeignKey(this ManyToOneMapping manyToOneMapping, string foreignKeyName)
{
if (!manyToOneMapping.IsSpecified("ForeignKey"))
manyToOneMapping.ForeignKey = foreignKeyName;
}
}