I have running MongoDB server, created test1 database with collection called zips. (taken from http://media.mongodb.org/zips.json). Now I want to read it from my application using Morphia.
following morphia tutorial(https://github.com/mongodb/morphia/wiki/GettingStarted):
I created maven project, and upadated dependencies(https://github.com/mongodb/morphia/wiki/Dependencies). now my project contain only entity class and main.
Entity class:
package com.mycompany.morphia;
import com.sun.corba.se.spi.ior.ObjectId;
import org.mongodb.morphia.annotationsEntity;
import org.mongodb.morphia.annotations.Id;
#Entity
public class MyEntity {
#Id String _id; //maybe ObjectId ?
String city;
Object loc;
Integer pop;
String state;
}
and main class
package com.mycompany.morphia;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import java.io.IOException;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.Morphia;
public class App
{
public static void main( String[] args ) throws IOException
{
MongoClient m = new MongoClient("localhost", 27017);
Datastore ds = new Morphia().createDatastore(m, "test1");
MyEntity e = ds.find(MyEntity.class).get();
System.out.println( e.city.toString());
System.in.read();
}
}
Still while debugging I got null. I don't know how to check if I'm connected to my db, and how to properly query it.
Use ObjectId instead of String
com.sun.corba.se.spi.ior.ObjectId is the wrong package — use org.bson.types.ObjectId instead
What does e.toString() give you?
If you're getting a null, then you're connected to the database. Your output suggests that the first document in that collection doesn't contain a field called "city."
The problem was in my #Entity
public Object loc;
Object type caused the problem. I simply removed it.
Related
I want to get the SearchOutput data object by calling a query(#Query method) with natural joins of 3 tables. but when the query runs it shows an error.
I have tried to fetch the data in my spring boot controller class. But its not working because of the error
package com.example.mysqlproj.model;
import lombok.*;
public class SearchOutput {
private String hotel_name;
private String room_type;
private int price;
}
package com.example.mysqlproj.dao;
import com.example.mysqlproj.model.Room_Type;
import com.example.mysqlproj.model.SearchOutput;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.Collection;
import java.util.Date;
import java.util.List;
public interface RoomTypeDao extends CrudRepository<Room_Type,Integer> {
#Query(value="select new SearchOutput(hotel_name , room_type,(price*(?4)*(?3)*(1.15))) from Room_type natural join Hotel natural join True_contract where (?1 >= start_date and ?2 <= end_date and ?3 <=available_rooms and ?4<= max_adults )", nativeQuery = true)
List<SearchOutput[]> checkHotelList(Date from, Date to, int rooms, int adults, int total_nights);
}
The Error:
No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [com.example.mysqlproj.model.SearchOutput]] with root cause
My target is to fetch a searchOutput object array when the query gets called.
Are there any solutions for this. Thanks in advance
The response type from the query is
List<Map<String, Object>> .
Please change the method return type to this.
I am new to Spring Jpa and Hibernate. I am trying to fetch data using a custom function from an Oracle db. I could define an entity along with its related service, implementation and repository. In addition, I created a new custom Oracle dialect by using registerFunction as you will see below.
So I have two questions:
1) In my Oracle db, the function sits under a different schema. Do I need to specify its schema? If so how? Or will hibernate find it automatically?
I will be asking my second question at the end of this post after providing my full stacktrace...
Here is my full stack trace:
MyOracle10gDialect
package blog;
import org.hibernate.dialect.Oracle10gDialect;
import org.hibernate.dialect.function.StandardSQLFunction;
public class MyOracle10gDialect extends Oracle10gDialect {
public MyOracle10gDialect() {
super();
registerFunction("my_function", new StandardSQLFunction("my_function"));
}
}
application.properties
...
spring.jpa.database-platform=blog.MyOracle10gDialect
...
Entity:
package blog.models;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "item", schema = "WOS_SOURCE")
public class WosItem {
#Id
#Column(nullable = false)
private String UT;
#Column(nullable = false)
private String TI;
public String getUT() {
return UT;
}
public void setUT(String UT) {
this.UT = UT;
}
public String getTI() {
return TI;
}
public void setTI(String TI) {
this.TI = TI;
}
public WosItem(String UT, String TI) {
this.UT = UT;
this.TI = TI;
}
public WosItem() { }
#Override
public String toString() {
return "WosItem{" +
"UT='" + UT + '\'' +
", TI='" + TI + '\'' +
'}';
}
}
Service:
package blog.services;
import blog.models.WosItem;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public interface WosItemService {
List<WosItem> findAll();
WosItem findById(String id);
String find_ut(Long ut_seq);
}
Implementation:
package blog.services;
import blog.models.WosItem;
import blog.repositories.WosItemRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class WosItemServiceJpaImpl implements WosItemService {
#Autowired
private WosItemRepository wosItemRepository;
#Override
public List<WosItem> findAll() {
return this.wosItemRepository.findAll();
}
#Override
public WosItem findById(String id) {
return this.wosItemRepository.findOne(id);
}
#Override
public String find_ut(Long ut_seq) {
return this.wosItemRepository.find_ut();
}
}
Repository:
package blog.repositories;
import blog.models.WosItem;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
#Repository
public interface WosItemRepository extends JpaRepository<WosItem, String> {
#Query("SELECT function('my_function', input) FROM WosItem wos");
String find_ut();
}
So in my Oracle db I can use this function as shown below:
select other_schema.my_function(aa.input) from my_schema.TABLE aa;
For ex. say aa.input is 332708100009 then it returns 000332708100009
As for my second question:
2) How can I carry out this process in jpa? I am aware that my repository is not correct at all. I get an error like "Annotations are not allowed here". I could not find a way to remedy this.
Thanks in advance.
EDIT ON THROWN EXCEPTION:
Caused by: java.lang.IllegalStateException: No data type for node: org.hibernate.hql.internal.ast.tree.MethodNode
\-[METHOD_CALL] MethodNode: 'function (my_function)'
+-[METHOD_NAME] IdentNode: 'my_function' {originalText=my_function}
\-[EXPR_LIST] SqlNode: 'exprList'
\-[NAMED_PARAM] ParameterNode: '?' {name=ut_seq, expectedType=null}
Unfortunately if you want to use the JPA 2.1 feature of the custom function call in your Select statement then you will need to perform some additional actions before you can use it.
When you use it in your where statement then it works without any additional actions, but as i wanted to use it for one of my projects inside the select just as you did then you would need to:
1) Extend the hibernate dialect and register your function(s):
package com.mypkg.dialect;
import org.hibernate.dialect.Oracle10gDialect;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.type.StringType;
public class CustomOracle10gDialect extends Oracle10gDialect {
public CustomOracle10gDialect() {
super();
registerFunction("my_function"
, new StandardSQLFunction("my_function", new StringType()));
}
}
2) Edit your hibernate.dialect property of your session factory to point to that custom implementation:
<property name="hibernate.dialect" value="com.mypkg.dialect.CustomOracle10gDialect"/>
Update
If the function needs to be called from a certain schema then this would be suggested:
registerFunction("my_function"
, new StandardSQLFunction("schema.my_function", new StringType()));
Further reading -> native function calls
I'm working on an Android project which uses Google App Engine for backend as described here: Using Android & Google App Engine on Android Studio.
I have some model classes on the backend side like User and Item, and I'm trying to return a list of Items user has.
public List<Ref<Item>> getItems() {
return items;
}
When I try to Sync Project with Gradle Files, I get this error:
Error:Execution failed for task ':backend:appengineEndpointsGetClientLibs'.
There was an error running endpoints command get-client-lib: Parameterized type com.googlecode.objectify.Ref≤backend.model.Item> not supported.
I checked some other questions here and was able to build the project without errors by adding #ApiResourceProperty(ignored = AnnotationBoolean.TRUE) annotation to my getter method. But after adding this line, I cannot see this method on Android app side.
Any idea how to make it possible to get a list of Items on Android side?
I did it by saving/retrieving object that contains serialized collection. Class Lesson implements Serializable.
Language.java
import java.io.Serializable;
import java.util.List;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Serialize;
#Entity
public class Language {
#Id
private String key;
private String title;
#Serialize
private List<Lesson> lessons; //here collection
//getters/setters ommited
}
LanguageService.java
import static com.googlecode.objectify.ObjectifyService.ofy;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.Named;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.ObjectifyService;
import com.minspok.entity.Language;
#Api(name = "langapi", version = "v1", description = "langapi")
public class LanguageService {
static{
ObjectifyService.register( Language.class );
}
#ApiMethod(name = "get")
public Language getLanguage(#Named("key") String key){
Language language = ofy().load().key(Key.create(Language.class,
key)).now();
return language;
}
#ApiMethod(name = "create")
public void createLanguage(Language language){
ofy().save().entity(language);
}
}
Helpful reading: https://github.com/objectify/objectify/wiki/Entities
I'm trying to use the Play framework (Java) to simply read some data from a few Oracle tables, probably even use a few complex queries later on. I'm following a tutorial but I'm having some issues retrieving the data.
My Model class look like this:
package models;
import java.util.ArrayList;
import java.util.List;
import play.libs.F;
import javax.persistence.*;
import com.avaje.ebean.*;
import play.db.ebean.*;
#Entity
#Table(name="TABLESPACE.CAT_BONDS")
public class Cat_Bond extends Model {
#Id
public String symbol;
public String database;
public String tickType;
public String assetClass;
public String sourcePlatform;
public String sourceExchange;
public static Finder<String, Cat_Bond> find = new Finder<String, Cat_Bond>(String.class,Cat_Bond.class);
public Cat_Bond(){}
public Cat_Bond(String symbol, String database, String tickType, String assetClass,
String sourcePlatform, String sourceExchange) {
this.symbol = symbol;
this.database = database;
this.tickType = tickType;
this.assetClass = assetClass;
this.sourcePlatform = sourcePlatform;
this.sourceExchange = sourceExchange;
}
/*
* retrieve all rows from the 'cat_bonds' table
*/
public static List<Cat_Bond> findAll(){
//return new ArrayList<Cat_Bond>(cat_bond);
return find.all();
}
/*
* Find by EAN
*/
public static Cat_Bond findByEan(String symbol){
return find.where().eq("symbol", symbol).findUnique();
}
}
My controller class:
package controllers;
import java.util.List;
import views.html.*;
import models.Cat_Bond;
import play.data.Form;
import play.mvc.*;
public class Cat_Bonds extends Controller {
private static final Form<Cat_Bond> cat_bondForm = Form.form(Cat_Bond.class);
public static Result list(){
List<Cat_Bond> cat_bond = Cat_Bond.findAll();
return ok(list.render(cat_bond));
}
And the application.conf entry looks like:
#Oracle
db.default.driver=oracle.jdbc.OracleDriver
db.default.url="jdbc:oracle:thin:#server.uk.net.intra:port/ALIAS"
db.default.user=user
db.default.password=pass
# Evolutions
# ~~~~~
# You can disable evolutions if needed
evolutionplugin=disabled
Problem is when the call to list is made in the controller then to findAll() in the model I get the error:
**[PersistenceException: Query threw SQLException:ORA-00904: "T0"."SOURCE_EXCHANGE": invalid identifier Bind values:[] Query was: select t0.symbol c0, t0.database c1, t0.tick_type c2, t0.asset_class c3, t0.source_platform c4, t0.source_exchange c5 from TABLESPACE.CAT_BONDS t0 ]**
#Column(name="xx")
Was required above each variable defined in the model class that was to be mapped to the table column.
You can use
clean
compile
~run
If it doesn't work properly, you can use #EntityConcurrencyMode(ConcurrencyMode.NONE) within your model class.
Update: I've created an example on GitHub to demonstrate my problem; HibernateMapTest currently fails due to the fact the HashMap key is a proxy object. I'm hoping someone can suggest a way I can query for the entity and fetch the map so that the test passes...
I'm simply trying to fetch the contents of a HashMap persisted in Hibernate, but I'm having some trouble finding the correct way to do it...
The HBM mapping is as follows, I did not create this but from my research it appears to be a ternary association mapping with a many-to-many relation. (Update: to simplify my question I've forced the map to lazy="false" to avoid my join):
<hibernate-mapping>
<class name="database.Document" table="document">
...
<map name="documentbundles" table="document_bundles" lazy="false">
<key column="id"/>
<index-many-to-many column="pkgitemid" class="database.PkgItem"/>
<many-to-many column="child" class="database.Document" />
</map>
</class>
</hibernate-mapping>
For simplicity I'm just currently just attempting to fetch all the records with this map data populated:
DetachedCriteria criteria = DetachedCriteria.forClass(Document.class);
criteria.add(Restrictions.eq("id", 1));
List<Document> result = hibernateTemplate.findByCriteria(criteria);
After last to false, I now get the contents of the Map without throwing a LazyInitializationException; but none of the key objects have been initialised properly. I've dumped a screenshot to clarify what I mean:
I know that the fields are populated in the database, and I suspect my fetching strategy is still to blame. How do you fetch a <map> in Hibernate correctly?
The error is due to the HibernateTemplate opening a Hibernate session to execute this query:
List results = hibernateTemplate.find("from database.Document d where d.name = 'doc1'");
and then immediately closing the session after the query is run. Then when looping through the keys, the session to which the map was linked is closed so the data cannot be loaded anymore, causing the proxy to throw the LazyInitializationException.
This exception means that the proxy can no longer load the data transparently because the session to which is linked too is now closed.
One of the main goals of the HibernateTemplate is to know when to open and close sessions. The template will keep the session open if there is an ongoing transaction.
So the key here is to wrap the unit test in a TransactionTemplate (the template equivalent to #Transactional), which causes the session to be kept open by the HibernateTemplate. Because the session is kept open, no more lazy initialization exceptions occur.
Modifying the test like this will solve the problem (notice the use of TransactionTemplate):
import database.Document;
import database.PkgItem;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
public class HibernateMapTest {
private static final String TEST_DIALECT = "org.hibernate.dialect.HSQLDialect";
private static final String TEST_DRIVER = "org.hsqldb.jdbcDriver";
private static final String TEST_URL = "jdbc:hsqldb:mem:adportal";
private static final String TEST_USER = "sa";
private static final String TEST_PASSWORD = "";
private HibernateTemplate hibernateTemplate;
private TransactionTemplate transactionTemplate;
#Before
public void setUp() throws Exception {
hibernateTemplate = new HibernateTemplate();
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.getHibernateProperties().put("hibernate.dialect", TEST_DIALECT);
sessionFactory.getHibernateProperties().put("hibernate.connection.driver_class", TEST_DRIVER);
sessionFactory.getHibernateProperties().put("hibernate.connection.password", TEST_PASSWORD);
sessionFactory.getHibernateProperties().put("hibernate.connection.url", TEST_URL);
sessionFactory.getHibernateProperties().put("hibernate.connection.username", TEST_USER);
sessionFactory.getHibernateProperties().put("hibernate.hbm2ddl.auto", "create");
sessionFactory.getHibernateProperties().put("hibernate.show_sql", "true");
sessionFactory.getHibernateProperties().put("hibernate.jdbc.batch_size", "0");
sessionFactory.getHibernateProperties().put("hibernate.cache.use_second_level_cache", "false");
sessionFactory.setMappingDirectoryLocations(new Resource[]{new ClassPathResource("database")});
sessionFactory.afterPropertiesSet();
hibernateTemplate.setSessionFactory(sessionFactory.getObject());
transactionTemplate = new TransactionTemplate(new HibernateTransactionManager(sessionFactory.getObject()));
}
#After
public void tearDown() throws Exception {
hibernateTemplate.getSessionFactory().close();
}
#Test
public void testFetchEntityWithMap() throws Exception {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
// Store the entities and mapping
PkgItem key = new PkgItem();
key.setName("pkgitem1");
hibernateTemplate.persist(key);
Document doc2 = new Document();
doc2.setName("doc2");
hibernateTemplate.persist(doc2);
Document doc1 = new Document();
doc1.setName("doc1");
HashMap<PkgItem, Document> documentbundles = new HashMap<PkgItem, Document>();
documentbundles.put(key, doc2);
doc1.setDocumentbundles(documentbundles);
hibernateTemplate.persist(doc1);
// Now attempt a query
List results = hibernateTemplate.find("from database.Document d where d.name = 'doc1'");
Document result = (Document)results.get(0);
// Check the doc was returned
Assert.assertEquals("doc1", result.getName());
key = (PkgItem)hibernateTemplate.find("from database.PkgItem").get(0);
Set<PkgItem> bundleKeys = result.getDocumentbundles().keySet();
// Check the key is still present in the map. At this point the test fails because
// the map contains a proxy object of the key...
Assert.assertEquals(key, bundleKeys.iterator().next());
}
});
}
}
and these are the test results and the log after the change:
This is a supplement to jhadesdev's answer, since I needed to do a little more work to get exactly what I was looking for.
In summary, you can't fetch a PersistedMap with a Hibernate query and immediately start using it like a typical Java hash map. The keys are always proxies; eager fetching / joining only fetches the map values, not the keys.
This means any code that deals with the hash map needs to be wrapped in a Hibernate transaction, which caused me some architectural problems as my data and service layers are separate.
I worked around this by iterating the hash map within a single transaction and replacing the keys with the ones originally passed in. I kept performance up by batching up the keys I want to fetch and retrieving them in one go:
// Build a list of keys we want to fetch in one go
final List<PkgItem> pkgItems = Arrays.asList(pkgItem1, pkgItem2, ...);
Map<PkgItem, Document> bundles = transactionTemplate.execute(new TransactionCallback< Map<PkgItem, Document> >() {
#Override
public Map<PkgItem, Document> doInTransaction(TransactionStatus transactionStatus) {
if (doc1.getId() == null) return null;
// Merge the parent document into this transaction
Document container = hibernateTemplate.merge(doc1);
// Copy the original package items into the key set
Map<PkgItem, Document> out = new HashMap<PkgItem, Document>();
for (PkgItem dbKey : container.getDocumentbundles().keySet()) {
int keyIndex = pkgItems.indexOf(dbKey);
if (keyIndex > -1) out.put(pkgItems.get(keyIndex), container.getDocumentbundles().get(dbKey));
}
return out;
}
});
// Now we can perform a standard lookup
assertEquals("doc2", result.get(pkgItem1).getName());
I can now use the map without Hibernate in the resulting code, with only a minimal performance hit. I've also updated the test in my example GitHub project to demonstrate how this can work.