I am trying to map the result of a couchbase query to a java reference type, so far I have found no way to do this.
How can I capture the following as a java reference type:
N1qlQueryResult result = couchbaseBucket.query(
N1qlQuery.simple("SELECT * FROM customers LIMIT 1"));
JsonObject cust = result.allRows().get(0).value();
How can I cast this 'cust' to a java object? What would be the best way of doing this, doesnt the couchbase SDK provide some solution to this?
There was a blog post published yesterday that shows you how to do this with couchbase spring-boot and spring data.
I'm not a Java expert at all, but it looks like you start by creating an entity class like this:
#Document
#Data
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
public class Building {
#NotNull
#Id
private String id;
#NotNull
#Field
private String name;
#NotNull
#Field
private String companyId;
// ... etc ...
}
Then, create a repository class.
#N1qlPrimaryIndexed
#ViewIndexed(designDoc = "building")
public interface BuildingRepository extends CouchbasePagingAndSortingRepository<Building, String> {
List<Building> findByCompanyId(String companyId);
// ... etc ...
}
Finally, you can use #Autowired in a service class or wherever to instantiate a BuildingRepository and start calling the methods on it. The full documentation for Spring Data Couchbase is available on docs.spring.io
Related
I have several indices where I save products:
product-example1
product-example2
product-example3
product-example4
product-example5
I have the a document in elastic search that has the same structure and it can used for different indices:
#Data
#org.springframework.data.elasticsearch.annotations.Document(indexName = "", type = "", createIndex = false)
public class ProductDocument {
#Id
private String id;
private String title;
private String seller;
private String releaseDate;
....
}
So basically I want to use same settings, same mappings same search service.
So I made indexName and type parametric in spring boot java, instead of creating 5 classes extending ProductDocument ?
#Autowired
private final ElasticsearchTemplate elasticsearchTemplate;
this.elasticsearchTemplate.createIndex("product-example1", loadFile("/files/settings.json"));
this.elasticsearchTemplate.putMapping("product-example1", "product-type1", loadFile("/files/mapping.json"));
this.elasticsearchTemplate.createIndex("product-example2", loadFile("/files/settings.json"));
this.elasticsearchTemplate.putMapping("product-example2", "product-type2", loadFile("/files/mapping.json"));
......
Now I want to create a ProductRepository but I don't have a class with defined index name. If I use generic class:
public interface DocumentRepository extends ElasticsearchRepository<ProductDocument, String> {
}
I get the error which is totally understable cause I created the index names in dynamic way:
lang.IllegalArgumentException: Unknown indexName. Make sure the indexName is defined. e.g #ProductDocument(indexName="foo")
So is it possible somehow to create repository for indexes that I created in dynamic way as described above, and pass the index name and type as parameter ?
Please help! I'm stuck.
I'm on Spring boot 1.4.x branch and Spring Data MongoDB.
I want to extend a Pojo from HashMap to give it the possibility to save new properties dynamically.
I know I can create a Map<String, Object> properties in the Entry class to save inside it my dynamics values but I don't want to have an inner structure. My goal is to have all fields at the root's entry class to serialize it like that:
{
"id":"12334234234",
"dynamicField1": "dynamicValue1",
"dynamicField2": "dynamicValue2"
}
So I created this Entry class:
#Document
public class Entry extends HashMap<String, Object> {
#Id
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
And the repository like this:
public interface EntryRepository extends MongoRepository<Entry, String> {
}
When I launch my app I have this error:
Error creating bean with name 'entryRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.model.MappingException: Could not lookup mapping metadata for domain class java.util.HashMap!
Any idea?
TL; DR;
Do not use Java collection/map types as a base class for your entities.
Repositories are not the right tool for your requirement.
Use DBObject with MongoTemplate if you need dynamic top-level properties.
Explanation
Spring Data Repositories are repositories in the DDD sense acting as persistence gateway for your well-defined aggregates. They inspect domain classes to derive the appropriate queries. Spring Data excludes collection and map types from entity analysis, and that's why extending your entity from a Map fails.
Repository query methods for dynamic properties are possible, but it's not the primary use case. You would have to use SpEL queries to express your query:
public interface EntryRepository extends MongoRepository<Entry, String> {
#Query("{ ?0 : ?1 }")
Entry findByDynamicField(String field, Object value);
}
This method does not give you any type safety regarding the predicate value and only an ugly alias for a proper, individual query.
Rather use DBObject with MongoTemplate and its query methods directly:
List<DBObject> result = template.find(new Query(Criteria.where("your_dynamic_field")
.is(theQueryValue)), DBObject.class);
DBObject is a Map that gives you full access to properties without enforcing a pre-defined structure. You can create, read, update and delete DBObjects objects via the Template API.
A last thing
You can declare dynamic properties on a nested level using a Map, if your aggregate root declares some static properties:
#Document
public class Data {
#Id
private String id;
private Map<String, Object> details;
}
Here we can achieve using JSONObject
The entity will be like this
#Document
public class Data {
#Id
private String id;
private JSONObject details;
//getters and setters
}
The POJO will be like this
public class DataDTO {
private String id;
private JSONObject details;
//getters and setters
}
In service
Data formData = new Data();
JSONObject details = dataDTO.getDetails();
details.put("dynamicField1", "dynamicValue1");
details.put("dynamicField2", "dynamicValue2");
formData.setDetails(details);
mongoTemplate.save(formData );
i have done as per my business,refer this code and do it yours. Is this helpful?
I have a document structure which has some generic class. For writing to mongodb everything is fine. But when reading documents from mongodb spring data converts document into object falsely. It converts a subdocument with another type. Both types (actual subcollection type and falsely converted type) are inherit from same abstract class.
Model Classes:(getter setters are generated by lombok )
#Data
public abstract class CandidateInfo {
private String _id;
}
#Data
public class CandidateInfoContainer<E extends CandidateInfo> {
private String _id;
private int commentCount = 0;
#Valid
private List<E> values = new ArrayList<>();
}
#Data
public class Responsibility extends CandidateInfo {
#NotNull
private String responsibilityId;
#ReadOnlyProperty
private String responsibilityText;
}
#Data
public class Experience extends CandidateInfo {
#Valid
private CandidateInfoContainer<Responsibility> responsibilities;
}
#Document
#JsonInclude(JsonInclude.Include.NON_NULL)
#Data
public class Candidate {
private String _id;
#Valid
private CandidateInfoContainer<Experience> experiences;
}
And if you create a mongoRepository like below:
#Repository
public interface CandidateRepository extends MongoRepository<Candidate,String>{
}
And use it like:
#Autowired
private CandidateRepository candidateRepository;
Candidate candidate = candidateRepository.findOne("documentId");
Then spring data mongo mapping converter creates candidates.experiences.responsibilities.values list as Experince list but it should be Responsibility list.
You can find a demo project in this link and more information about the issue. Can anyone point out what is wrong? Otherwise i have to write my own converter(demo has one)
If there is any unclear thing, you can ask.
Thanks.
I open an issue in spring-data-mongo here. Appareantly I caught a bug! Thanks everyone
Having trouble to create the right itnerface for my Query for this given Problem.
I have this entity:
public class TwoEntity extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
/*
* ATTRIBUTE
*/
private String groupName;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<OneEntity> oneList;
And the Crud Repositoy:
public interface TwoRepository extends CrudRepository<TwoEntity, Long> {
TwoEntityfindById(Long id);
TwoEntityfindByGroupName(String groupName);
List<TwoEntity> findBy????(OneEntity oe);
My Goal is to get All TwoEntities where OneEntitie is a element in the list of TwoEntity.
I´am using Spring boot and Hibernate to accomplish this. I cant delete the OneEntity Object from my Database because TwoEntity has OneEntity as ForeignKey in the List.
Is there anyway of get this to work with the given Tools from the Interface?
A List of available KeyWords can be found here: spring docs for crud
/E
I Guess I have a wrong Architecture. Currently I have a Unidirectional Relation between this Entities. I guess I have to make those entities bidirectional and delete them manuelle with oneList.setList(null).
BUT I´m not 100% sure. Open for Input.
You could use this:
List<TwoEntity> findByOneList_Id(Long oneEntityId)
But you need to extend from JpaRepository
public interface TwoRepository extends JpaRepository<TwoEntity, Long> {
The method will be translated to
twoEntity.oneList.id
Here official doc
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-property-expressions
Ok, I am using spring MVC 3.0 and I am adding a log entity as follows
#RooJavaBean
#RooToString
#RooEntity
public class Log {
#NotNull
#Size(max = 1000)
private String logMessage;
#NotNull
#ManyToOne
private Staff staff;
#NotNull
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(style = "M-")
private Calendar dateAndTime;
#NotNull
private Class owningClass;
}
I am looking at this guide for help. The question is how do I use the class object for, say Student, to find a particular student with id 10, or 20, ...
I was thinking something like this
Class c = Class.forName("My.Domain.Student"); //gives the bsae class
This is where i am not sure what to do. I want something like
Student student = c.find(10);
How can i accomplish something like this ?
I believe (I currently don't have Roo projects at hand, I'm using Manning Spring Roo In Action book for reference) that you can examine the content of Spring ROO ActiveRecord pattern impementation classes and see that the location by ID is implemented via a entity manager lookup:
public static Course Course.findCourse(Long id) {
if (id == null) return null;
return entityManager().find(Course.class, id);
}
As you can see you can pass whatever entity class reference you like to the enitity manager to do lookup based on the class and the id.
So you basically you need to get a reference to the EntityManager and call its find() method.