I need to convert data retrieved from Solr to specific class, I've tried 3 different ways, but each of them has some problem.
Method 1 : using 3rd party library - JSONUtil.
SolrDocument solrDocument = (SolrDocument) iterator.next();
String jsonString = JSONUtil.toJSON(solrDocument);
EventObject eventObject2 = gson.fromJson(jsonString, EventObject.class);
Method 2 : transform solrDocument to JsonString directly.
String jsonString2 = gson.toJson(solrDocument);
EventObject eventObject3 = gson.fromJson(jsonString2, EventObject.class);
Method 3 : transform solrDocument to JSONObject then convert to JsonString.
JSONObject object = new JSONObject(solrDocument);
String jsonStringFromJsonObject = object.toString();
EventObject eventObjectFromJsonObject = gson.fromJson(jsonStringFromJsonObject, EventObject.class);
Method 4 : using Java Beans
List<EventObject> EventObjects = response.getBeans(EventObject.class);
The result of Method1 can't handle fields which is Date or ArrayList Type. The result of Method2, Method3 and Method4 are all the same, they handle all fields well, however, ArrayList field are still empty.
Edit :
My Solr schema is as follows(only mention the 2 fields which can't transform correctly) :
<dynamicField name="*_Image_Infos" type="string" indexed="true" stored="true" required="false" multiValued="true" />
<dynamicField name="*_ss" type="string" indexed="true" stored="true" required="false" multiValued="true" />
My EventObject is as follows :
public List<EventObjectImageInfo> ImageInfos = new ArrayList<EventObjectImageInfo>();
public List<EventObjectColor> Colors = new ArrayList<EventObjectColor>();
Both of EventObjectImageInfo & EventObjectColor are my own classes.
Did I do anything wrong? Or is there any other way should I try? Thanks!
You can use Solr JavaBeans
Let's say i have the solr schema :
<field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
<field name="name" type="string" indexed="false" stored="true"/>
<field name="marks" type="long" multiValued="true" indexed="true" stored="true"/>
I have the Student class
public class Student {
#Field
String id;
#Field
String name;
#Field
ArrayList<Long> marks;
}
Now I can convert SolrDocumentList to List with javabeans
SolrDocumentList list; // you already have that
DocumentObjectBinder binder = new DocumentObjectBinder();
List<Student> dataList = binder.getBeans(Student.class, list);
Related
i have little bit trouble with deserialization of XML. I am only able to deserialize this xml by:
#JacksonXmlProperty(localName = "field")
#JacksonXmlElementWrapper(useWrapping = false)
List<Object> field;
This is my xml:
<Response>
<user>
<field attribute="x"></field>
<field attribute="y">false</field>
<field attribute="z">string</field>
</user>
<user>
<field attribute="x"></field>
<field attribute="y">false</field>
<field attribute="z">string</field>
</user>
</Response>
Problem is, that i want to replace Object in List<Object> field; with some specific class so i could access attribute and the value in field.
With Object, i am able to create something like this:
user='[{attribute=x}, {attribute=y, =false}, {name=z, =string}]
thanks a lot.
Found answer. I created new class that contains this elements:
#JacksonXmlProperty(isAttribute = true, localName = "attribute")
String attribute;
#JacksonXmlText
String value;
And replace the Object with this new class.
I'm working with an API which returns XML something like this:
<xyz-objects version="1.0">
<object pk="1" model="roll">
<field type="BigIntegerField" name="roll_number">1000000714</field>
<field type="CharField" name="status">DL</field>
<field name="scans">
<object pk="1" model="scan_stages">
<field type="DateTimeField" name="updated_on">11 Jul, 2017, 17:40</field>
</object>
</field>
</object>
</xyz-objects>
I'm using Jackson's XML mapper.
I tried writing a POJO object for this but that doesn't work.
How do I handle attributes of elements like type and name?
Can you exemplify?
Based on the investigation I did in https://github.com/FasterXML/jackson-module-kotlin/issues/138 here's a workaround that's a bit more typed that the JsonNode workaround by madhead
data class Field(
#JacksonXmlProperty(isAttribute = true)
val type: String,
#JacksonXmlProperty(isAttribute = true)
val name: String,
) {
#JacksonXmlText
lateinit var value: String private set
}
As you didn't provide the schema, it's hard to guess some parts of your model. Especially, it's hard to guess field model. So I will deserialize it into a JsonNode, dynamic object that can handle literally everything. JsonIgnoreProperties just in case you have some extra fields, not mentioned here.
First, create some data classes:
#XmlRootElement(name = "xyz-objects")
#JsonIgnoreProperties(ignoreUnknown = true)
data class XyzObjects(
#JacksonXmlProperty(isAttribute = true)
val version: String,
#JsonProperty(value = "object")
#JacksonXmlElementWrapper(useWrapping = false)
val objects: List<Object>
)
#XmlRootElement(name = "object")
#JsonIgnoreProperties(ignoreUnknown = true)
data class Object(
#JacksonXmlProperty(isAttribute = true)
val pk: String,
#JacksonXmlProperty(isAttribute = true)
val model: String,
#JsonProperty(value = "field")
#JacksonXmlElementWrapper(useWrapping = false)
val fields: List<JsonNode>
)
Answering your question: you can handle attrributes with by using isAttribute attribute of JacksonXmlProperty. Lists can be handled with JacksonXmlElementWrapper + JsonProperty (don't be fooled by name, it is used to handle plurals in names, thus making them more human readable in XML too).
In order to be able to work with data classes, you'll need to register Kotlin module with registerKotlinModule:
val text = """<xyz-objects version="1.0">
<object pk="1" model="roll">
<field type="BigIntegerField" name="roll_number">1000000714</field>
<field type="CharField" name="status">DL</field>
<field name="scans">
<object pk="1" model="scan_stages">
<field type="DateTimeField" name="updated_on">11 Jul, 2017, 17:40</field>
</object>
</field>
</object>
</xyz-objects>"""
val mapper = XmlMapper().registerKotlinModule()
val node = mapper.readValue<XyzObjects>(text)
println(node)
It will print:
XyzObjects(version=1.0, objects=[Object(pk=1, model=roll, fields=[{"type":"BigIntegerField","name":"roll_number","":"1000000714"}, {"type":"CharField","name":"status","":"DL"}, {"name":"scans","object":{"pk":"1","model":"scan_stages","field":{"type":"DateTimeField","name":"updated_on","":"11 Jul, 2017, 17:40"}}}])])
I was wondering if it's possible in JPA to define a generic entity like in my case PropertyBase and derive concrete entity classes like ShortProperty and StringProperty and use them with the SINGLE_TABLE inheritance mode?
If I try to commit newly created ElementModel instances (see ElementModelTest) over the EntityManager I always get an NumberFormatException that "value" can't be properly converted to a Short. Strangely enough if I define all classes below as inner static classes of my test case class "ElementModelTest" this seems to work.
Any ideas what I need to change to make this work?
I'm using EclipseLink eclipselink-2.6.0.v20131019-ef98e5d.
public abstract class PersistableObject implements Serializable {
private String id = UUID.randomUUID().toString();
private Long version;
}
public abstract class PropertyBase<T> extends PersistableObject {
private String name;
private T value;
}
public class ShortProperty extends PropertyBase<Short> {
...
}
public class StringProperty extends PropertyBase<String> {
...
}
public class ElementModel extends PersistableObject {
private StringProperty name = new StringProperty();
private ShortProperty number = new ShortProperty();
}
public class ElementModelTest extends ModelTest<ElementModel> {
#Test
#SuppressWarnings("unchecked")
public void testSQLPersistence() {
final String PERSISTENCE_UNIT_NAME = getClass().getPackage().getName();
new File("res/db/test/" + PERSISTENCE_UNIT_NAME + ".sqlite").delete();
EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
for (int i = 0; i < 10; ++i) {
ElementModel device = new ElementModel();
device.setName("ElementModel: " + i);
device.setNumber((short) i);
em.persist(device);
}
em.getTransaction().commit();
em.close();
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<entity-mappings version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd">
<mapped-superclass
class="PersistableObject">
<attributes>
<id name="id">
<column name="id" />
</id>
<version name="version" access="PROPERTY">
<column name="version" />
</version>
</attributes>
</mapped-superclass>
<entity class="PropertyBase">
<table name="PropertyBase" />
<inheritance />
<discriminator-column name="type"/>
<attributes>
<basic name="name">
<column name="name" />
</basic>
<basic name="value">
<column name="value" />
</basic>
</attributes>
</entity>
<entity class="StringProperty">
<discriminator-value>StringProperty</discriminator-value>
</entity>
<entity class="ShortProperty">
<discriminator-value>ShortProperty</discriminator-value>
</entity>
<entity class="ElementModel">
<table name="ElementModel" />
<inheritance />
<discriminator-column name="type"/>
<attributes>
<one-to-one name="name">
<join-column name="name" referenced-column-name="id" />
<cascade>
<cascade-all />
</cascade>
</one-to-one>
<one-to-one name="number">
<join-column name="number" referenced-column-name="id" />
<cascade>
<cascade-all />
</cascade>
</one-to-one>
</attributes>
</entity>
</entity-mappings>
Your problem is that PropertyBase<T> is an entity with field value being persistable. Your database needs to map that field type to a column type, and you have three entities that have different java types for the same field: PropertyBase<T> is generic and has itself no idea what type its value field is, StringProperty says it is a String and ShortProperty says that is a Short. So that is a conflict.
In order to overcome this problem, you make field value transient, and for every subtype of PropertyBase<T> (like StringProperty) you can define a new persitable property with different names, eg.
StringProperty will have a private String stringValue, ShortProperty will have a private Short shortValue, and every field will be mapped to different DB column.
PS: I cannot explain why it works when you make all the classes static inner.
Im making an email client in java. When user creates mail with attachment(document), it saves all the data about email message in database but in multiple tables, like attachement title in Document_table.title, number of message in msgnumber.num, date in msgnumber.date, name of sender in Official_Person.name and OfficialPerson.secondname.
How do i retrieve all this data and display it (im using Jtable for this)? I know how to get data if it saved in one table but not multiple. please help me.
one format has many documnets.
DOCUMENT:
#Entity
#Table(name="DOCUMENT"
,schema="Default"
)
public class Document implements java.io.Serializable {
#ManyToOne
#JoinColumn(name = "FormatID")
private Format format;
#Id
#Column(name = "DocumentID", unique = true, nullable = false)
private int documentId;
FORMAT :
#Entity
#Table(name="FORMAT"
,schema="Default"
)
public class Format implements java.io.Serializable {
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "FormatID")
private Set<Document> documents = new HashSet();
#Id
#Column(name = "FormatID", unique = true, nullable = false)
private int formatId;
format.hbm
<hibernate-mapping>
<class name="entity2.Format" table="FORMAT">
<id name="formatId" type="int">
<column name="FormatID" length="2000000000" />
<generator class="native" />
</id>
<set name="documents" table="DOCUMENT"
inverse="true" lazy="true" fetch="select">
<key>
<column name="FormatID" not-null="true" />
</key>
<one-to-many class="entity2.Document" />
</set>
document.hbm
<hibernate-mapping>
<class name="entity2.Document" table="DOCUMENT">
<id name="documentId" type="int">
<column name="DocumentID" length="2000000000" />
<generator class="native" />
</id>
<many-to-one name="format" class="entity2.Format" fetch="select">
<column name="FormatID" not-null="true" />
</many-to-one>
i want to retrieve all documents for format 1:
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Format f = (Format) session.get(Format.class, 1);
System.out.println(f.getName());
System.out.println(f.getDocuments());
documents is empty? where am i wrong?
If you define a relationship between classes, for example:
class Person {
#OneToMany(cascade=CascadeType.ALL,
fetch= FetchType.EAGER)
private Set<Email> emails = new HashSet();
// getters/setters and some other attributes are not shown
When you read an object from the database, you will get another object that has a relationship with it automatically.
Session s = HibernateUtil.getSessionFactory().openSession();
Person p = (Person) s.get(Person.class, 1);
s.close();
System.out.println(p.getName());
System.out.println(p.getEmails());
The following is an example of bidirectional one to one relationship.
class Person {
#OneToOne(cascade=CascadeType.ALL)
private Address address;
class Address {
#OneToOne(mappedBy=”address”)
private Person person
Hibernate is an ORM tool - the "O" stands for "object". Start with an Email object that maps to your table and columns. Then use HQL to query for Email instances that meet a particular restriction.
JTable or web page are display issues that are separate from the manner in which you query for objects.
You just write the query using a select statement for all of the values you wish to retrieve. Hibernate will return an array with those values in it with the indices in the same order as your select statement.
SELECT
FROM Person AS P, Address AS A, Order AS O, User AS U
WHERE P.id = 5
AND A.personId = P.id
AND O.personId = P.id
AND U.personId = P.id
This will return an array containing {person, address, List, User}
I have a class auction like
public class Auction extends LightEntity implements IsSerializable
{
private long AuctionId;
private Date StartTime;
private Date EndTime;
}
i need to perform write an hql using restriction which chooses all auction whose end time has not yet completed.
my xml mapping file for the auction class is
<hibernate-mapping>
<class name="com.BiddingSystem.Models.Auction" table="AUCTION">
<id name="AuctionId" type="long">
<column name="AUCTIONID" />
<generator class="native" />
</id>
<property name="StartTime" type="java.util.Date">
<column name="STARTTIME" />
</property>
<property name="EndTime" type="java.util.Date">
<column name="ENDTIME" />
</property>
..
.
.
.
>
First of all, you should definitely respect the Java naming conventions : variables and fields start with a lower-case letter in Java (auctionId, startTime, endTime).
Now your question :
either you compute the current time, and pass it as a parameter to your query :
Date now = new Date();
Query q = session.createQuery("select a from Auction a where a.endTime > :now");
q.setTimeStamp("now", now);
return q.list();
or you use expressions supported by HQL :
Query q = session.createQuery("select a from Auction a where a.endTime > current_timestamp()");
return q.list();