MY POJO looks like this:
#Document(collection = "users")
public class User {
#Id
private String id;
String username;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
I am able to save the object's values in the mongodb by calling mongoDBClient.save(userObj); as bellow:
public void save(Object paramObject) {
mongoOperations.save(paramObject);
}
The problem with this save api is that it's returning void. I want to get the same object which was saved. How can I achieve that?
paramObject is viable for introspection after save. It represents it's persistent state at that stage.
For example, the driver is responsible to assign the id on your behalf.
In addition, all properties which you don't set yourself and are designated to be populated by spring data - such as properties annotated with #CreatedDate - are also available after the save() method (assuming auditing is configured).
In any case, the Id is set. Later you can query for the same object by calling findById(paramObject.getId(), User.class)
Related
I am trying to have table per class configuration with Morphia + MongoDb
#Entity("user")
public class User{
#Id
private ObjectId id;
private String username;
public void setId(ObjectId id){
this.id = id;
}
public ObjectId getId(){
return this.id;
}
public void setUsername(String username){
this.username = username;
}
public String getUsername(){
return this.username;
}
}
And Assistant
#Entity("assistant")
public class Assistant extends User{
private String fullname;
public String getFullname(){
return this.fullname;
}
public void setFullname(String fullname){
this.fullname = fullname;
}
}
I Want to have a user document and assistant document with same ObjectId. How Do this?
MongoDB is not a relational database, you will need to change your mental & database model.
If somebody is an assistant, all the data will go to the assistant collection. There are no joins (except for aggregations, but you don't want to do this for a simple user lookup), so all the information should be in one entity.
You could even keep the assistants in the user collection. Or speaking in more general terms: Keep all subclasses in the entity of its parent class.
Morphia will automatically store the Java class for every entity, so you can simply filter on that. And since there is no strict schema, there are also no null values since the JSON only stores the available attributes.
I am using similar code to what is listed in: How to map one class with multiple tables in Hibernate/javax.persistance?
I was trying to write a sample login program, based on above example I map my user class to secondary table where I store password field. now when I retrieve back user entity. I also get secondary table field so password is also available in user object.
Is it possible, that during registration I want to use secondary table storage method but when I read back. it should not return password back with user?
How can I achieve this? I am looking for some JPA way like #transient ignore the particular column.
I wouldn't go for such implementation.
Best practice is to never store a clear-text password, but a digest instead:
#Entity
public class Account
{
#Column
private String username;
#Column(length = 32)
private String password;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = DigestUtils.md5Hex(password);
}
}
It's an uncommon requirement, and JPA patterns will do their best to fight against you :)
But... some way may still be possible:
using Entity Listeners:
#Entity
public class Account
{
#Column
private String username;
#Column
private String password;
#PostLoad
public void postLoad()
{
password = null;
}
}
be careful: when loaded inside a transaction, a null password may be eventually flushed on commit.
removing getter for password:
if you put annotations only on fields, you can remove getPassword() method. Even if the field is populated on load, it's not accessible by external java code.
using a #Transient combination:
#Entity
public class Account
{
#Column
private String username;
#Column
private String password;
#Transient
private String password2;
public String getPassword()
{
return password2;
}
public void setPassword(String password)
{
this.password = password;
this.password2 = password;
}
}
I would like to update a field of a record which has been already been stored in the database. How can I achieve that? All of the examples I've come across so far are either in Python/Php or an older version of MongoDB (Java) and the api is not longer current.
Basically I would like to load an object with a particular userId in memory and change its username value. (I'd like to refer you to the code below)
Thank you so much
EDIT
So far I've got the following code:
public class UserDAO {
MongoOperations mongoDb;
public UserDAO(){
mongoDb = MongoDBInstanceFactory.getMongoDBinstance();
}
public User getUserByUsername(String username){
Query searchUserQuery = new Query(Criteria.where("username").is(username));
return mongoDb.findOne(searchUserQuery, User.class);
}
public User getUserById(String id){
Query searchUserQuery = new Query(Criteria.where("id").is(id));
return mongoDb.findOne(searchUserQuery, User.class);
}
public User addUser(String username){
mongoDb.save(new User(username));
return getUserByUsername(username);
}
}
#Document(collection = "users")
public class User {
public User(String username) {
this.username = username;
}
public User() {
}
#Id
private String id;
private String username;
//getter, setter, toString, Constructors
/**
* #return the id
*/
public String getId() {
return id;
}
/**
* #return the username
*/
public String getUsername() {
return username;
}
}
#RequestMapping(value = "/registerUser")
public #ResponseBody
String registerUser(#RequestParam(value = "username") String username, HttpServletResponse response) throws IOException {
sb = new StringBuilder();
user = userDao.getUserByUsername(username);
if (user == null) {
user = userDao.addUser(username);
userQueryPhaseDao.addUserQueryPhase(user.getId(), null, "0");
sb.append("1|").append(user.getId());
response.addCookie(new Cookie("userId", user.getId()));
} else {
sb.append("0|User with that handle already exists!");
}
return sb.toString();
}
Thank you for your time
To change an existing document, use the method DBCollection.update.
The method takes two parameters.
The first parameter tells MongoDB which document to update. It works exactly like find or findOne.
The second is the document that document will be replaced with. When you only want to update a single field and not replace the whole document, you need to use the $set operator.
I have a class like this...
#Entity
public class User{
private String userId;
#Id
public String getUserId(){
return userId;
}
public void setUserId(String userId){
this.userId = userId;
}
}
#Embeddible
public class RegPk{
private String serial;
private String userId;
....
}
#Entity
#IdClass(RegPk.class)
public class Registration {
private String userId, serial;
private User user
#Id
#Column(name="SRL_C")
public String getSerial() {return serial;}
public void setSerial(String serial) {this.serial = serial;}
#ManyToOne(cascade={CascadeType.REFRESH})
#JoinColumn(name="USERID", referencedColumnName="USERID", nullable = false)
public User getUser() {return user;}
public void setUser(User user) {this.user = user;}
#Id
#Column(name="USERID", nullable = false)
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
RegPk pk = new RegPk();
pk.setSerial(dr.getSerial());
pk.setUserId(dr.getUserId());
Registration userOld = em.find(Registration.class, pk);
But when I try to run it I get null back. I swear I thought I had it working so...
1.) is this kind of thing even possible?
2.) what am I doing wrong?
Yes, it's possible, provided you use the MapsId annotation. Otherwise, you have two different fields mapped to the same column, which is invalid.
The javadoc provides an example which almost matches exactly with your situation.
I hope someone can assist me with this. I'm trying to pass an customer id and customer name from a database result using rpc in gwt to the client. I found a way to pass one variable but I can't find a way to pass them both where the id is attached to the name. Can someone post a code example on how to do this. If you need more info let me know.
That is a simple java limitation. Just wrap the 2 fields in an object.
As David Nouls said, you could just use an object, e.g.
import com.google.gwt.user.client.rpc.IsSerializable;
public class Customer implements IsSerializable {
private String id;
private String name;
public Customer(String id, String name) {
this.id = id;
this.name = name;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}