Child properties with JDO and AppEngine - google-app-engine

I have the following code:
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class A {
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#PrimaryKey
private Key key;
#Persistent
private B b;
#Persistent
private int id;
// ...
}
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class B {
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#PrimaryKey
private Key key;
#Persistent
private int id;
// ...
}
Now what I need to be able to do, is retrieve an instance of B, and refer to it from an instance of A like this:
B b = DAL.getBById(1);
A a = new A();
a.setB(b);
When I pass a to the makePersistent() method of the PersistenceManager, two things that I don't need happen:
1) a new instance of B is created
2) the reference A makes to b is null
Could someone tell me what I am doing wrong?
Thanks!

A field value can contain an instance of a Serializable class, storing the serialized value of the instance in a single property value of the type Blob. To tell JDO to serialize the value, the field uses the annotation #Persistent(serialized=true). Blob values are not indexed and cannot be used in query filters or sort orders.
Here is an example of a simple Serializable class that represents a file, including the file contents, a filename and a MIME type. This is not a JDO data class, so there are no persistence annotations.
import java.io.Serializable;
public class DownloadableFile implements Serializable {
private byte[] content;
private String filename;
private String mimeType;
// ... accessors ...
}To store an instance of a Serializable class as a Blob value in a property, declare a field whose type is the class, and use the #Persistent(serialized = "true") annotation:
import javax.jdo.annotations.Persistent;
import DownloadableFile;
// ...
#Persistent(serialized = "true")
private DownloadableFile file;
I your case you can use
import java.io.Serializable;
public class B implements Serializable {
private int xx;
....
..........
}
Then declare it in your data class
#Persistent(serialized = "true")
private B b;

Related

How to update tables with many-to-many relationship when performing crud operations in Spring Boot

I'm trying to create a Spring Boot backend for my project. In the database I have Deck and Word tables with a many-to-many relationship connected via DeckWord table. The bridge table has additional fields and a composite PK consisting of the other 2 tables' PK's.
I am not sure about how I should structure the crud operations in my project. Say I'm trying to add a new word and it should be assigned to a certain deck. What model's controller should handle the post operation in that scenario: Word or DeckWord? Should the Deck's List<DeckWord> be updated as well?
UPDATE:
Included the models, omitted the getters, setters and constructors
#Entity
#Table(name = "deck")
public class Deck {
#Id
#SequenceGenerator(
name = "deck_sequence",
sequenceName = "deck_sequence",
allocationSize = 1
)
#GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "deck_sequence"
)
#Column(name = "deck_id")
private Long id;
#Transient
private Boolean learnt;
private String name;
#OneToMany(mappedBy = "deck", cascade = CascadeType.ALL)
private List<DeckWord> deckwords;
#ManyToOne
#JoinColumn(name="appuser_id",referencedColumnName="appuser_id")
private Appuser appuser;
}
and
#Entity
#Table(name = "word")
public class Word {
#Id
#SequenceGenerator(
name = "word_sequence",
sequenceName = "word_sequence",
allocationSize = 1
)
#GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "word_sequence"
)
#Column(name = "word_id")
private Long id;
private String definition;
private String transcription;
#OneToMany(mappedBy = "word", cascade = CascadeType.ALL)
private List<DeckWord> deckwords;
}
and the bridge table:
#Embeddable
class DeckWordKey implements Serializable {
#Column(name = "deck_id")
Long deckId;
#Column(name = "word_id")
Long wordId;
}
#Entity
#Table
public class DeckWord {
#EmbeddedId
DeckWordKey id;
#ManyToOne
#MapsId("deckId")
#JoinColumn(name = "deck_id",referencedColumnName="deck_id")
Deck deck;
#ManyToOne
#MapsId("wordId")
#JoinColumn(name = "word_id",referencedColumnName="word_id")
Word word;
private Boolean learnt;
private LocalDate last_checked;
private WordGroup wordGroup;
}
Answering your questions:
What model's controller should handle the post operation in that scenario: Word or DeckWord?
Given that a Word should always be assigned to a Deck, then I would use a POST request to the URL "/decks/{deckId}/words" to create a new Word. The request body should include definition and transcription.
Should the Deck's List be updated as well?
Yes, it must. For that, you need to use deckId that you receive as a path parameter.

JPA entity relation in table which sharing same key as foreign and primary?

Now, I have two tables.
1st Table (Object Table):
RefNo (PK) --> auto ascending
Type
Status
...
2nd Table (Object Detail Table):
RefNo (PK) --> FK reference from 1st Table
PolicyNo
DepNo
...
Entity for Object.
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long refnno;
#OneToOne(mappedBy = "obejctTwo")
private ObjectDetail objectDetail;
private String type;
private String status;
Entity for ObjectDetail
#Id
private long refnno;
#OneToOne
#JoinColumn(name = "refnno")
#MapsId
private Object object;
private String policyNo;
private String depNo;
How can I save the Object using jpaRepository for Object which include ObjectDetail inside Object JSON but without knowing the reffno(PK) which is auto generated by db.
{
"objectDetail": {
"policyNo": "12345678",
"depNo": "ABC"
},
"type": "new",
"status": "pending"
}
Would it not be possible to cascade the saving with the annotation #OneToOne(cascade = CascadeType.PERSIST) in the class Object?
I would then create the two objects with the available details, set the relationship and save the class Object.
object.setObjectDetail(objectDetail);
objectdetail.setObject(object);
repository.save(object);
The key of object would be set automatically and objectDetail would get the key from object.
Edit: Entity Example
I was slightly surprised that the code did not work. Therefore, I implemented this for myself. It works perfectly with Spring Boot version 2.3.2.RELEASE and spring-boot-starter-data-jpa.
Your issue might be #OneToOne(mappedBy = "obejctTwo") because this mapping does not exist.
Object
#Entity
public class Object {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long refnno;
#OneToOne(mappedBy = "object",
cascade = CascadeType.ALL,
orphanRemoval = true)
private ObjectDetail objectDetail;
private String type;
private String status;
public setObjectDetail(ObjectDetail objectDetail) {
this.objectDetail = objectDetail;
objectDetail.setObject = this;
}
// Getters and remaining setters...
}
I added a slightly modified setter for objectDetail which helps to keep the bidirectional OneToOne mapping synchronised.
BTW: I changed the datatype of refnno to the object Long. Classes are considered to be better for database entities because than you can test them properly for null. Furthermore, this id can then be used for a JpaRepository<Object, Long>.
ObjectDetail
#Entity
public class ObjectDetail {
#Id
private Long refnno;
#OneToOne
#JoinColumn(name = "refnno")
#MapsId
private Object object;
private String policyNo;
private String depNo;
// Getters and setters...
}
Repository and Execution
I created a simple repository.
public interface ObjectRepository extends JpaRepository<Object, Long> {
}
I then used the save(Object entity) method to persist a new Object with a new ObjectDetail.
Object object = new Object();
object.setType("new");
ObjectDetail objectDetail = new ObjectDetail();
objectDetail.setPolicyNo = "999";
object.setObjectDetail(objectDetail);
objectRepository.save(object);

Insert null instead of 0 in the database for an integer

I'm using hibernate And I have a class Structure that contains an id, name And a structure object
Structure(ID,NAME,Structure) The default value of the id is 0 because it is an integer.
This object can contain a parent object of the same type or not.
So at the time of inserting if parent object is null I want to have id of the parent object in the null database and not 0.
Here is my modele
#Entity
public class Structure implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long idt_structure;
private String name;
#ManyToOne
#JoinColumn(name="idt_parent_structure")
private Structure structure;
// Getters and setters
}
And here is the function for insertion
public void save(){
if(this.idt_structure != null){
Structure structureParent = (Structure) structureService.findStructureById(idt_structure);
structure.setStructure(structureParent);
}
else{
structure.setStructure(structure);
}
structureService.addStructure(structure);
structures=structureService.listStructures();
}

solrj index child documents with multiple levels

I'm moving from multiple cores to a single core with nested documents.(reason being matching/scoring from multiple cores is limited)
To achieve this I'm trying to index a nested structure using solrJ.
I've tested the following code but I get an error "BookDetail cannot have more than one Field with child=true"
How can I avoid this? Is this a solrj limitation?
Indexing is done as followed:
- Solr and solrj version 5.3.1
HttpSolrClient mytestcore=new HttpSolrClient("...");
mytestcore.add(dob.toSolrInputDocument(new Book());//should have some initialization
The structure is below(but most unused fields are removed).
public class Book implements Serializable {
#Field
private String id;
#Field
private String type;
#Field(child = true)
private List<BookDetail> details;
...
}
public class BookDetail implements Serializable {
#Field
private String id;
#Field
private String type;
#Field(child = true)
private List<BookMetaData> bookMetaData;
#Field(child = true)
private List<BookContent> pages;
...
}
public class BookMetaData implements Serializable {
#Field
private String id;
#Field
private String type;
...
}
public class BookContent implements Serializable {
#Field
private String id;
#Field
private String type;
#Field
private String content;
...
}
Edit:
Currently solved it by making seperate SolrInputDocuments for each document type and add them with addChildDocument.(as seen on other answers on stackoverflow) But this solution doesn't use the annotation "child = true" anymore...

How to store classes containing Lists of classes that also contain Lists using GAE and Objectify?

I have a Java model similar to:
public class Country {
#Id private String id;
private CurrencyId currencyId;
private List<Province> provinceList;
...
}
public class Province {
#Id private String id;
private Gobernor gobernorId;
private List<City> cityList;
...
}
public class City {
#Id private String id;
private String name;
...
}
I want to store that data using objectify. However, as Country data might change, I also want to store the date the Country data has been stored, so I think I should store an entity such as:
public class CountryListEntity {
#Id private String id;
private List<Country> countryList;
private Date storeDate;
}
Note I will only have one entity of kind CountryListEntity with the Id "root", if I can store it like that. I know very little about both how google apps stores data and how objectify works. I've tried many combinations of #Embedded, but I got many errors, i.e.
Cannot place array or collection properties inside #Embedded arrays or collections
Can anyone tell me how to define these classes? A snippet of the code needed to store and retrieve this "root" entity, would be highly appreciated!
#Embedded collections are transformed into a series of collection fields in the
low-level Entity. That's why one level embedding is all you can do.
If you are going to store/load all data at once and if your entities are as simple as the ones in your example you can put #Serialized annotation for your lists inside #Embedded lists.
You can find out more from this discussion.
The problem with this approach is that your low-level embeddings won't be able to be indexed.
public class CountryListEntity {
#Id private String id;
#Embedded
private List<Country> countryList;
private Date storeDate;
}
public class Country implements Serializable {
private String id;
private CurrencyId currencyId;
#Serialized
private List<Province> provinceList;
// ...
}
public class Province implements Serializable {
private String id;
private Gobernor gobernorId;
#Serialized
private List<City> cityList;
// ...
}
public class City implements Serializable {
private String id;
private String name;
// ...
}

Resources