Check if User object exists in #DBRef List<User> - spring

I'm making use of MongoDB, Spring Data and Spring MVC.
I have a user model which has a list of contacts:
class User {
#DBRef
private List<User> contacts = new ArrayList<User>();
public List<User> getContacts() {
return contacts;
}
}
I currently have 4 users inside my database. 1 user has a particular contact (who is referred to the same collection by id).
Now, I want to check whether a user has a particular contact. I use the following code:
User userLoggedIn = userService.getLoggedInUser(); //user object
User contact = userService.findById(contactId); //contact
if(userLoggedIn.getContacts().contains(contact)) {
System.out.println("Has this contact.");
}
This output message is not shown. However, if I print the list of contacts of the user and their id's, I clearly see that the contact is inserted inside the list of the user.
I noticed that if I print the hashCode of the contact object and the one that is inside the list, I get a different value, so I assume that even though the details are the same, the object itself isn't.
How can I approach this problem by simply checking whether he is inside the list. Or should I just compare by id?
Otherwise stated: how can I check whether an object exists in the contacts list?

You should override an equals method in User.
From JavaDoc:
boolean contains(Object o)
Returns true if this list contains the specified element. More
formally, returns true if and only if this list contains at least one
element e such that (o==null ? e==null : o.equals(e)).
With equals you must override and hashCode
http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html/persistent-classes.html#persistent-classes-equalshashcode

Related

how to select a user id and merge the updated user inputs in respective fields

i have a controller with #SessionAttributes("user_email") now i wish to do a merge operation for this particular user_email in session
i have a dao implementation class which performs merge operation as follows:
#Override
public boolean mergeusers(Users users) {
session.getCurrentSession().merge(users); //saves or updates the lawyer details //
return true;
}
but even though i give session.getcurrentSession it merges the new user input as a new user in the database instead of merging/updating the fiel that matches the session's user_email
im new to this could someone please tell me what im doing wrong
two options
populate the Id of the user before merging or
find the user from the database (findById) and update the data and merge it

can not addRange of items to var using linq and c#

I have a following list of users:
var roles = userRoleRepository.Get(q => q.user_id.Equals(username, StringComparison.InvariantCultureIgnoreCase));
roles has two properties one is (ID,Name) ,how can i add a collection to this after i get the list?since roles,does not have add or addrange,i want to add("124","Jack")
It seems to me that UserRoleRepository is an object of one of your (company's) own classes. This class has a Get function that has some return value.
Alas you forgot to tell us the returned type. From the code snippet, I assume that the returned object is not a sequence of objects, but one single object, probably something that you'd call a UserRole. The returned UserRole is the one in the userRoleRepository that has a user_id that equals some string userName.
As the Get function returns only one UserRole it is not a meaningful action to add a collection to this one object, unless this UserRole has a function to add a collection. But as you told us: your UserRole does not have such a function.
Or are you a bit sloppy in your description and do you want to add some UserRoles to the collection of UserRoles that would be the return of your Get function? Alas again: you didn't give us a definition of the return value of your Get function.
If Get returns one UserRole and you want the combination of this fetched UserRole together with your own sequence of UserRoles, do the following:
UserRole fetchedUserRole = userRoleRepository.Get(...);
List<UserRole> userRoles = new List<UserRole>();
userRoles.Add(fetchedUserRole);
return userRoles.Concat(myOwnUserRoleCollection);
If on the other hand Get returns a sequence of USerRole, the code would be even simpler:
IEnumerable<UserRole> fetchedUserRoles = userRoleRepository.Get(...);
return fetchedUserRoles.Concat(myOwnUserRoleCollection);

CacheEvict from Iterable collection

I have 2 method like this :
first, i'm get users deposit
#Override
#Transactional
#Cacheable(value = "deposits")
public Set<Deposit> getUserDeposit() {
User user = userRepository.findOneByUsername(
securityHolder.getUserDetails().getUsername());
Set<Deposit> deposits = user.getBalance().getDeposits();
return deposits;
}
and second, when save task entity which contain a one deposit as relationship i want evict from cache deposit by id :
(spring data interface)
#CacheEvict(value = "deposits", key = "#entity.deposit.id", condition = "#entity != null")
<S extends T> List<S> save(Iterable<S> entity);
but that no work.
CacheEvict works on an item not an iterator on items. There's a smell in your code: if you look at the SpEL expressions they are written as entity was the object to evict while its parameter type clearly says it's different.
There is another issue with the get. You are putting something in the cache with no key and the content depends on the connected user. You should make that information part of the key. Right now each new call overrides the content of the cache. Worse if you cache one user and then call that method with a different logged in user it'll get the deposit of another user!

Partial Entity Updates in WebAPI PUT/POST

Say you have a repository method to update a Document:
public Document UpdateDocument(Document document)
{
Document serverDocument = _db.Documents.Find(document.Id);
serverDocument.Title = document.Title;
serverDocument.Content = document.Content;
_db.SaveChanges();
return serverDocument;
}
In this case, the entity has two properties. When updating a Document, both of these properties are required in the JSON request, so a request to PUT /api/folder with a body of
{
"documentId" = "1",
"title" = "Updated Title"
}
would return an error because "content" was not provided. The reason I'm doing this is because, even for nullable properties and properties that the user doesn't update, it seems safer to force the client to specify these fields in the request to avoid overwriting unspecified fields with nulls serverside.
This has led me to the practice of always requiring every updatable property in PUT and POST requests, even if it means specifying null for those properties.
Is this cool, or is there a pattern/practice that I haven't learned about yet that might facilitate partial updates by sending only what is needed over the wire?
The best practice in API design is to use HTTP PATCH for partial updates.
In fact, use cases like yours are the very reason why IETF introduced it in the first place.
RFC 5789 defines it very precisely:
PATCH is used to apply partial modifications to a resource.
A new method is necessary to improve interoperability and prevent
errors. The PUT method is already defined to overwrite a resource
with a complete new body, and cannot be reused to do partial changes.
Otherwise, proxies and caches, and even clients and servers, may get
confused as to the result of the operation. POST is already used but
without broad interoperability (for one, there is no standard way to
discover patch format support).
Mark Nottingham has written a great article about the use of PATCH in API design - http://www.mnot.net/blog/2012/09/05/patch
In your case, that would be:
[AcceptVerbs("PATCH")]
public Document PatchDocument(Document document)
{
Document serverDocument = _db.Documents.Find(document.Id);
serverDocument.Title = document.Title;
serverDocument.Content = document.Content;
_db.SaveChanges();
return serverDocument;
}
Is this cool, or is there a pattern/practice that I haven't learned
about yet that might facilitate partial updates by sending only what
is needed over the wire?
A good practice of doing a POST or PUT is to only include values that you need for that specific request. In doing the UpdateDocument you should ask yourself what "really should be done here"? If you have a hundred fields on that object do you need to update all of them or only part of them. What "action" are you really trying to do?
Let's have an illustration for those questions, say we have a User object that has the following fields:
public class User {
public int Id {get;set;}
public string Username {get;set;}
public string RealName {get;set;}
public string Password {get;set;}
public string Bio {get;set;}
}
You then have two use cases:
Update the profile of a User
Update the password of a User
When you do each of those you will not, or it's a good idea to, have one update method that will do both. Instead of having a generic UpdateUser method you should have the following methods:
UpdateProfile
UpdatePassword
Methods that accepts fields that they just need, nothing more, nothing less.
public User UpdateProfile(int id, string username, string realname, string bio) {
}
public User UpdatePassword(int id, string password) {
}
Now comes the question:
I have a use case that a "user action" allows for an update on
multiple fields where some of the fields can have "no input" from the
user but I don't want to update that field in my model.
Suppose a user updates his/her profile and provided values for Username, RealName but not for Bio. But you do not want to set Bio as null or empty if it has a value already. Then that becomes a part of your application's business logic and that should be handled explicitly.
public User UpdateProfile(int id, string username, string realname, string bio) {
var user = db.Users.Find(id);
// perhaps a validation here (e.g. if user is not null)
user.Username = username;
user.RealName = realname;
if (!string.IsNullOrEmptyWHiteSpace(bio)) {
user.Bio = bio;
}
}

Can't Persist Field to Aspnet_Users via NHibernate/ActiveRecord

I'm using ActiveRecord with NHibernate on the backend. I've set up a mapping for Users; I can create/retrieve/register users without any issues.
I now want to add an association called Role to my users (many users per role). I've created the appropriate Role class, tables, data, etc. and everything seems to be working on that end as well.
The problem is that when I save a user and associate a Role, that association does not persist to the database.
I've added a RoleId (int16) column to the aspnet_Users table to match the Role table's Id (int16) column. I've tried using Save and SaveAndFlush without success.
Here's some code:
Role superUser = Role.First(r => r.name == "Super User");
User me = User.First(r => r.UserName == myUserName);
me.Role = superUser;
me.Save(); // Or: SaveAndFlush
When debugging, I can see the association on the objects when they're saved (i.e. me.Role is not null and has the right attributes/properties/etc.) However, when I look at the database, the RoleId value for that user is still NULL. (SaveAndFlush doesn't make a difference.)
What am I missing?
I've read somewhere on SO that extending the users table is usually done by adding another table and linking the two by a foreign key; I assume the classes would then use inheritance by composition for the new ExtendedUser class. Assuming I don't want to go that route, why isn't this working? Is it because of the specific ASP.NET MVC stored procedures et. all?
Some relevant mapping:
[ActiveRecord("aspnet_Users", Mutable = false)]
public class User : ActiveRecordLinqBase<User>
{
[PrimaryKey(PrimaryKeyType.Assigned)]
public Guid UserId { get; set; }
// ...
[BelongsTo("RoleId", Cascade = CascadeEnum.SaveUpdate)]
public Role Role { get; set; }
}
[ActiveRecord]
public class Role : ActiveRecordLinqBase<Role>
{
[PrimaryKey]
public int Id { get; set; }
// ...
[HasMany(Inverse = true)]
public IList<User> Users { get; set; }
[Property]
public string Name { get; set; }
}
Edit: mutable="false" - this clearly stands that entity is read only, which is the source of your problem.
Immutable classes, mutable="false", may not be updated or deleted by the application. This allows NHibernate to make some minor
performance optimizations.
Also:
I believe that you need to have cascading defined. You are not saving just the entity itself but also reference to other entity. Use attributes, fluent config or hbml to define this the way you need. Here are the cascading options:
Here is what each cascade option means:
none - do not do any cascades, let the users handles them by
themselves.
save-update - when the object is saved/updated, check the assoications and save/update any object that require it (including
save/update the assoications in many-to-many scenario).
delete - when the object is deleted, delete all the objects in the assoication.
delete-orphan - when the object is deleted, delete all the objects in the assoication. In addition to that, when an object is
removed from the assoication and not assoicated with another object
(orphaned), also delete it.
all - when an object is save/update/delete, check the assoications and save/update/delete all the objects found.
all-delete-orphan - when an object is save/update/delete, check the assoications and save/update/delete all the objects found. In additional to that, when an object is removed from the assoication and not assoicated with another object (orphaned), also delete it.
You may want to read this article.

Resources