A few days ago I've started developing a Backend for Mobile Applications using Google App Engine and Google Cloud Endpoints.
Initially I deployed a first version with the following entity fields:
#Entity
public class Tweet {
#Id
private String id;
private String user;
private String text;
private String date;
private int count;
private String linkTweet;
After a while, I added other fields:
#Entity
public class Tweet {
#Id
private String id;
private String user;
private String text;
private String date;
private int count;
private String linkTweet;
private String imageHttp;
private String imageHttps;
private String userId;
In the datastore I see changes, but when I go to https://myappid.appspot.com/_ah/api/tweetendpoint/v1/tweet I see only the old fields, there aren't the imageHttp imageHttps userId fields :(
Where I'm wrong?
I did the same change and it works fine. The only difference between my code and yours is that I am using JDO and have the tag (#Persistence) before each attribute.
#PersistenceCapable(detachable="true")
public class Test implements Serializable {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private String id;
...
#Persistent
private String newAttribute;
}
NOTE: if you don't have data in new fields, you will not see them in response.
This is an appengine issue. Google guys should fix it soon:
https://code.google.com/p/googleappengine/issues/detail?id=9686
Related
lets say i a MCV Rest Controller to update my Account document in mongo db.
Account.class
public class Account extends Credentials {
private static final long serialVersionUID = 1L;
private String email;
private String password;
private Boolean admin;
private String street;
private String postalcode;
private String city;
private String country;
private String phone;
private String birthday;
private String image;
}
email, password are fields to be writable only during signup procedure.
admin is a field only to be writable by administrators.
The rest of the fields can be updated by an "edit account" html UI.
Providing a RESTfull method like this will give all normal users access to all fields:
#RequestMapping(value = "upsert", method = RequestMethod.POST)
public ResponseEntity<Account> upsert(#RequestBody Account acc) throws Exception {
Provider entity = providerRepository.save(acc);
return new ResponseEntity<Account>(entity, HttpStatus.OK);
}
If i flag the "special" fields with #JsonProperty for read access only then the above update will remove them from the db during save operation.
What is the best way to separate the "special" fields from the "normal" fields?
I'm trying to isolate some core entities from my project. The idea of this is to share the same users, roles, etc. between many applications.
So, I have this User entity structure from core application, using a database called core:
#Entity
public class MyUser implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
#Column(unique = true)
private String username;
private String password;
private String salt;
#ManyToMany(fetch = FetchType.EAGER)
private Set<Role> roles;
private Boolean isAccountNonExpired;
private Boolean isAccountNonLocked;
private Boolean isCredentialsNonExpired;
private Boolean isEnabled;
...
}
On the other hand, I have this other entity from the final application, using a database called myapplication:
#Entity
public class Employee extends MyUser {
private static final long serialVersionUID = 1L;
#Type(type = "date")
private Date birthDate;
#Type(type = "date")
private Date marriageDate;
private Long employeeNum;
private Integer workHs;
#OneToMany
private List<Role> canAssignRoles;
}
I created two datasources and session factories in hibernate.cfg.xml, one for each database, but I cannot achieve the purpose.
How you can see, one entity is mapped to core database, and the other one is mapped to the myapplication database. The Employee entity has a OneToMany mapping to Role.
I have no idea of how to solve this. When Hibernate is creating the database entities, it raises an error when trying to create the entities for myapplication.
I have an entity called ReferenceForm which contains an AutoPopulatingList of ReferenceItems. It looks like this:
#Entity
public class ReferenceForm implements Serializable{
private static final long serialVersionUID = -5633788166190438576L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long id;
#lob
private AutoPopulatingList<ReferenceItem> referenceItems;
}
If I add no annotation at all to the AutoPopulatingList, the field type which hibernate creates is varbinary(255). This causes string truncation errors. To work around this, I used the #lob annotation. This felt questionable at the time, but it worked fine. At this point I was just using HSQLDB.
Now the application needs to run against MSSQL. I have generated the schema using Hibernate, and referenceItems ia an image column on the ReferenceForm table. The items themselves are stored in the ReferenceItem table.
Is #lob an appropriate annotation here?.
EDIT: ReferenceItem looks like this:
#Entity
public class ReferenceItem implements Serializable {
private static final long serialVersionUID = -9077063073733429102L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long id;
private Title title;
private String firstName;
private String surname;
private String positionHeld;
private String institutionCompany;
#Embedded
private Address address;
#Embedded
private Telephone telephone;
private String email;
private boolean existingReference;
private String fileName;
public ReferenceItem() {
}
...getters and setters
}
SECOND EDIT:
Thanks to Willome for suggesting using #OneToMany. In the end, this is what worked.
//from
#lob
private AutoPopulatingList<ReferenceItem> referenceItems;
//to
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<ReferenceItem> referenceItems = new AutoPopulatingList<ReferenceItem>(ReferenceItem.class);
#OneToMany accurately describes the nature of the relationship
Use the interface (List) instead of the implementation when defining the field. See http://docs.jboss.org/hibernate/core/3.3/reference/en/html/collections.html
Define the CascadeType, otherwise this error appears on saving the entity: org.hibernate.TransientObjectException: object references an unsaved transient instance
Make the FetchType EAGER otherwise you cannot load the form in a different transaction: this error appears: failed to lazily initialize a collection of role: ReferenceForm.referenceItems, could not initialize proxy - no Session
You should replace your #Lob annonation with a #OneToMany and replace the AutoPopulatingList with a collection-valued field declared as an interface type (Check out the topic 6.1. Persistent collections on this link http://docs.jboss.org/hibernate/core/3.3/reference/en/html/collections.html.)
//#Lob
#OneToMany(mappedBy = "referenceForm")
private AutoPopulatingList<ReferenceItem> referenceItems; //fail AutoPopulatingList is not an interface
#OneToMany(mappedBy = "referenceForm")
private Set<ReferenceItem> referenceItems; // OK with Set/Collection/List
Thanks to Willome for suggesting using #OneToMany. In the end, this is what worked.
//from
#lob
private AutoPopulatingList<ReferenceItem> referenceItems;
//to
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<ReferenceItem> referenceItems = new AutoPopulatingList<ReferenceItem>(ReferenceItem.class);
#OneToMany accurately describes the nature of the relationship
Use the interface (List) instead of the implementation when defining
the field. See
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/collections.html
Define the CascadeType, otherwise this error appears on saving the
entity: org.hibernate.TransientObjectException: object references an
unsaved transient instance
Make the FetchType EAGER otherwise you
cannot load the form in a different transaction: this error appears:
failed to lazily initialize a collection of role:
ReferenceForm.referenceItems, could not initialize proxy - no Session
I'm getting into problems with JPA. I'm trying to implement a database that allows users to follow other users and be followed.
I think I'd need (summing up) something like this:
USER_TABLE: id | userName
RELATIONSHIP_TABLE: id | follower | followed | acceptation
I have two entities (also summed up):
#Entity
public class User implements Serializable {
#Id
private Long id;
private String userName;
#OneToMany
private Collection<Relationship> followings;
}
#Entity
public class Relationship implements Serializable {
#Id
private Long id;
private User follower;
private User followed;
private boolean accepted;
}
My problem is that I'm not sure if it's possible to do this, because I obtain more tables that the two that I need.
Can anybody help me?
Thanks and sorry about my english.
You obtain more tables because you did not make the associations bidirectional. JPA has no way to know that Relationship.follower is the other side of the User.followings if you don't tell:
#Entity
public class User implements Serializable {
#OneToMany(mappedBy = "follower")
private Collection<Relationship> followings;
// ...
}
#Entity
public class Relationship implements Serializable {
#ManyToOne
#JoinColumn(name = "follower")
private User follower;
#ManyToOne
#JoinColumn(name = "followed")
private User followed;
// ...
}
The documentation of course explains how that works.
Hey guys, my question is about persisting an entity in JDO. I have created a class, StoredOPDSFeed, whose members persist correctly. However, none of its member objects persist correctly. The class is as follows:
#PersistenceCapable
public class StorableOPDSFeed implements Serializable {
private static final long serialVersionUID = 1L;
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private String primaryKey;
#Persistent
private String locale;
#Persistent
private Date parseDate;
#Persistent
private String title;
#Persistent
private String href;
#Persistent
#Element(dependent = "true")
private ArrayList<OPDSEntry> entries;
#Persistent
#Element(dependent = "true")
private ArrayList<OPDSLink> links = new ArrayList<OPDSLink>();
#Persistent
#Embedded
private SearchDescription searchDescription;
#Persistent
private boolean isStart = false;
#Persistent
#Element(dependent = "true")
private ArrayList<OPDSFacetGroup> facet_groups = new ArrayList<OPDSFacetGroup>();
... and accessors, etc.
}
All of the simple members such as locale, title, href, etc persist correctly. However, all of the complex ones such as searchDescription do not appear in the datastore. There is no reference to them whatsoever, no foreign key, nothing. It's like they are completely ignored. Does anyone have any idea why?
Per request, here is the code for OPDSLink:
#PersistenceCapable
public class OPDSLink implements Serializable {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
private String encodedKey;
private static final long serialVersionUID = 1L;
#Persistent
private String href;
#Persistent
private String rel;
#Persistent
private String type;
#Persistent
private String price;
#Persistent
private String currency;
#Persistent
private String dcformat;
#Persistent
private String title;
... and accessors, etc.
}
The GAE JDO documentation states that in one-to-one relationships both involved entities require a key field.
http://code.google.com/appengine/docs/java/datastore/jdo/relationships.html#Owned_One_to_One_Relationships
If the other entity is embedded as intended in your example, the other class (e.g. SearchDescription) requires a #EmbeddedOnly annotation:
http://code.google.com/appengine/docs/java/datastore/jdo/dataclasses.html#Embedded_Classes
In general I found the the following blog interview a good starting point to see what the GAE JDO implementation supports and what not (especially in comparison to third party frameworks such as Objectify and Twig):
http://borglin.net/gwt-project/?page_id=604