i have couchbase document like following
{
"contentTimestamp": 1470216079085,
"version": 12,
"content": [
{
"text": "ABC",
"params": {
"TYPE": "TEXT"
}
}
],
"readers": {
"u_id_1": 0,
"u_id_2": 0,
},
"contributors": [
{
"id": "u_id_1"
}
]
}
Document class
#Document
public class ContentDoc implements Serializable{
private static final long serialVersionUID = 1L;
#Id
private String id;
#Field
private Integer version = 12;
#Field
private List<Content> content = new ArrayList<>();
#Field
private Map<String, Object> readers = new HashMap<>();
//etc
//getter setter
}
Service
#Service
public interface ContentDocRepository extends CrudRepository<ContentDoc, String> {
public List<ContentDoc> findByReadersIn(String reader) throws Exception;
}
Testcase
#RunWith(SpringJUnit4ClassRunner.class)
public class Tests {
#Autowired
private ContentDocRepository contentDocRepository;
#Test
public void cotentDocRepoTest(){
List<ContentDoc> contents = contentDocRepository.findByReadersIn("u_id_1");
Assert.assertNotNull(contents);
System.out.println(contents)
}
}
I wrote code as per above but not able to retrieve result always got empty arraylist.
Anyone knows what going wrong with my code and how can i execute query with child element?
Thanks in advances.
After long RND and experiment i got solution,
we dont have way to finding child element with method name so we need
to do as per my following answer
Steps :
Create custom view in couchbase as per following
viewname : findContentByUser
function (doc, meta) {
if(doc._class == "package.model.ContentDoc") {
for(var i=0; i < doc.contributors.length; i++){
emit(doc.contributors[i].id, null);
}
}
}
Repository : binding viewname and designDocument with impl method as per following
#Repository
public interface ContentDocRepository extends CrudRepository<ContentDoc, String> {
#View(viewName = "findContentByUser", designDocument="dev_content")
public List<ContentDoc> findByContributors_id(String id);
}
Finally Got result :)
You don't need to create a view anymore, just use the #N1qlPrimaryIndexed and #ViewIndexed annotations and it should work out-of-the-box:
#N1qlPrimaryIndexed
#ViewIndexed(designDoc = "building")
public interface BuildingRepository extends
CouchbasePagingAndSortingRepository<Building, String> {
List<Building> findByCompanyId(String companyId);
}
I answered a very similar question here Using IN clause in couchbase N1Ql #query or use findAll(keys) from couchbase JPA
And you can follow my tutorial here:
https://blog.couchbase.com/couchbase-spring-boot-spring-data/
#Service
public interface ContentDocRepository extends CrudRepository<ContentDoc, String> {
#View(viewName = "findContentByUser", designDocument="dev_content")
public List<ContentDoc> findByContributors_id(String id) throws Exception;
}
Related
I'm trying to get the data from MSSQL database using below logic. Couldnt identify the option to prepare a single query (SQL or JPQL) to get the repository reponse as MyTestSTO.Can someone suggest me the options available to acheive this.
Expected object Format :
{
"id": "1",
"name": "Test",
"CabInfo": {
"CabStatus": 0,
"CabStatusStr": "Active",
"CabFunctionalArea": {
"FunctionalAreaId": 3
},
"CabApplication": {
"ApplicationId": 333,
"ApplicationAcronym": "OBM Router"
}
}
}
And JPARepository Class is :
public interface FloorPlanRepositoryExt extends JpaRepository<Sites, Long> {
//Other APIs on Sites Table.
Can we use multiple news in below query ?
#Query(value = "select new TestDTo(sp.id,sp.name,sp.cabStatus,sp.cabStatusStr,
sp.functionalArea,sp.applicationId,sp.ApplicationAcronym) from SpacePower sp where sp.roomId=:roomId)
public List<TestDTo> getRoomSpacesCabByRoomId(#Param("roomId")Integer roomId);
}
My custom DTO is below:
class TestDTo implements serializable{
private String id;
privateString name;
private CabInfo cabInfo
//Setters and getters and Constructor
}
class CabInfo{
private String cabStatus;
private String CabStatusStr;
private CabFunctionalArea cabFunctionalArea;
private CabApplication CabApplication;
//Setters and getters and Constructor
}
In select query you expect TestDTo but in return method you define RoomSpacesCabDTO
I would like to store a method in a helper class and call that method from another class. The method also fetches data from a jpa repository.
For some reason when i call the method from the helper class, i get an error : Cannot resolve method 'getDocumentListByProduit' in 'DocumentHelper'. The method name doesn't show in IDE's autocompletion either. It's like the method isn't mapped for some reason.
Any hints why? thanks in advance.
class from where i wish to call the method:
#Entity
#Table(name = "document", schema = "table_name")
public class Document {
private int id;
private String url;
private String type;
private String titre;
private String description;
#Autowired
private DocumentHelper dh;
...
public Map<String, List<Document>> getDocumentListByProduit(int id){
Map<String, List<Document>> ret = dh.getDocumentListByProduit(id);
return ret;
}
the helper class :
#Component
public class DocumentHelper {
#Autowired
private DocumentRepository dr;
public DocumentHelper() {
}
public Map<String, List<Document>> getDocumentListByProduit(int id) {
Map<String, List<Document>> ret = new HashMap<>();
List<Document> listImg = new ArrayList<>();
List<Document> listOther = new ArrayList<>();
List<Document> dList = new ArrayList<>();
try {
dList = dr.getDocumentListByProduit(id);
for (Document tDoc : dList) {
if (tDoc.getType().equals("image")) {
listImg.add(tDoc);
} else {
listOther.add(tDoc);
}
}
ret.put("imageCollection", listImg);
ret.put("otherCollection", listOther);
} catch (Exception e) {
throw new DAOException("Une erreur est survenue : " + e.getMessage());
}
return ret;
}
}
then the Repository:
public interface DocumentRepository extends JpaRepository<Document, Integer> {
// in method getDocumentListByProduit in DocumentHelper
#Query(value = "SELECT * FROM DOCUMENT D, DOCUMENT_PRODUIT DP WHERE D.id = DP.id_document AND DP.id_produit = :id_produit;", nativeQuery = true)
List<Document> getDocumentListByProduit(#Param("id_produit") int id_produit);
}
JPA doesn't use the Spring container to instantiate its entities, so Spring does not inject dependencies into entities by default.
You can inject dependencies into objects not managed by the Spring container using #Configurable as described here. This approach requires configuring AspectJ into the project.
Another way would be injecting dependencies manually after JPA constructed an entity using AutowireCapableBeanFactory#autowireBean. This approach may be considered as a bad practice because of repetitiveness if you need it more than in one case.
I have a requirement where I need a subclass as object while creating a json payload.
EventBase
public class EventBase {
#JsonProperty("event_id")
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
PaymentCapture (the sub class)
#JsonTypeName("resource")
public class PaymentCapture extends EventBase {
#JsonProperty("parent_payment")
private String parentPayment;
public String getParentPayment() {
return parentPayment;
}
public void setParentPayment(String parentPayment) {
this.parentPayment = parentPayment;
}
}
And I need a json payload in below form:
{
"id": "someId",
"resource": {
"parent_payment": "23434"
}
}
I can understand this violates inheritance relationship, but just want to know if there is any solution available or not.
The closest I could get when having similar problem was creating an adapter class. This solution prints one extra property which might be possible to be ignored if for example some inheritance was allowed but I assume that not and use just the declared classes in addition to the adapter, which is like:
#RequiredArgsConstructor
public class PaymentCaptureAdapterClass {
#NonNull
#JsonProperty
private PaymentCapture resource;
#JsonProperty
private String getId() {
return resource.getId();
}
}
using this with code:
ObjectMapper om = new ObjectMapper();
om.enable(SerializationFeature.INDENT_OUTPUT);
PaymentCapture pc = new PaymentCapture();
pc.setId("someId");
pc.setParentPayment("23434");
log.info("\n{}", om.writeValueAsString(new AdapterClass(pc)));
prints something like:
{
"resource" : {
"event_id" : "someId", // might be able to be ignored
"parent_payment" : "23434"
},
"id" : "someId"
}
Regarding Spring HATEOAS Resource Wrapper vs ResourceSupport extention, i have:
public class FolderDto<T> implements Serializable {
private Number id;
private String name;
private final List<FolderDto<T>> folders;
private final List<T> items;
...
}
public class BoardDto implements Serializable {
private String name;
private Integer id;
private boolean shared;
...
}
#Test
public void test() throws Exception {
FolderDto<Resource<BoardDto>> folder = new FolderDto<Resource<BoardDto>>(0, null);
FolderDto<Resource<BoardDto>> child = new FolderDto<>(1000, "root");
folder.getFolders().add(child);
child.getItems().add(new Resource<>(new BoardDto(333,"whiteBoard", true)));
Resource<FolderDto<Resource<BoardDto>>> resource = new Resource<>(folder, linkTo(methodOn(BoardController.class).getBoards(null)).withSelfRel());
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(System.out, resource);
}
The result will be:
{
"id":0,
"nodes":[
{
"id":1000,
"name":"root",
"leaves":[
{
"content":{
"id":333,
"name":"whiteBoard",
"shared":true
},
"links":[{"rel":"board","href":"http://localhost/internal/boards/333"}]
}
]
}
],
"links":[{"rel":"self","href":"http://localhost/internal/boards"}]
}
How can i have this without the content element wrapper using Resource ?
In order to split responsibilities the rest controller logic (hateoas) entities should be as clean as possible and not have dependencies to other libs.
Desire result (obtained with extends ResourceSupport) :
{
"id":0,
"nodes":[
{
"id":1000,
"name":"root",
"leaves":[
{
"id":333,
"name":"whiteBoard",
"shared":true,
"links":[{"rel":"board","href":"http://localhost/internal/boards/333"}]
}
]
}
],
"links":[{"rel":"self","href":"http://localhost/internal/boards"}]
}
I am saving a Document in the Couchbase using Spring. For some fields extra information is added.
POJO:
#Document public class PlayerTxn implements Serializable {
private static final long serialVersionUID = -2569497126561L;
#Id private String id;
#Field private Date txnDate;
#Field private BigDecimal wagerAmount;
#Field private BigDecimal pointsAwarded;
#Field private String segment;
RequiredResult:
{ "txnDate": 234234234324, "wagerAmount": 234.33, "pointsAwarded":
23.2, "segment": "xxx" }
End result:
{ "_class": "com.app.model.PlayerTxn", "segment":
"xxx", "wagerAmount": {
"intCompact": 24312,
"scale": 2,
"precision": 5,
"stringCache": "243.12" }, "pointsAwarded": {
"intCompact": -9223372036854776000,
"scale": 38,
"precision": 0,
"intVal": {
"signum": 1,
"bitCount": 0,
"mag": [
3800,
-457875904,
-1778440383,
-1805069212,
295579091
],
"lowestSetBit": 0,
"firstNonzeroIntNum": 0,
"bitLength": 0
} }, "txnDate": 1466417747057 }
Had to write a customConverter for BigDecimal.
But still "_class" is being added in the Document. Any idea how can I remove it?
Looks like you need to add custom converters for BigDecimal values, something like:
// extend or add a customized couchbase config like this
public class CustomCouchbaseConfig extends AbstractCouchbaseConfiguration {
#Override
public CustomConversions customConversions() {
return new CustomConversions(Arrays.asList(
BigDecimalToString.INSTANCE,
StringToBigDecimalConverter.INSTANCE));
}
#WritingConverter
public static enum BigDecimalToString implements Converter<BigDecimal, String> {
INSTANCE;
#Override
public String convert(BigDecimal source) {
// or a more appropriate implementation
return source.toString() ;
}
}
#ReadingConverter
public static enum StringToBigDecimalConverter implements Converter<String, BigDecimal> {
INSTANCE;
#Override
public BigDecimal convert(String source) {
return new BigDecimal(source);
}
}
}
Be sure, to make those converter methods null-safe!
See the Spring Data Couchbase Reference for more information:
http://docs.spring.io/spring-data/couchbase/docs/2.1.2.RELEASE/reference/html/#datatypes
Edit:
Regarding the _class attribute, see this SO question and the answer by Oliver Giercke for the reasoning behind _class.
The question is aimed at MongoDB but can easily be translated for Couchbase as well.