Mapping POJOs and Using Reference in MongoDB using Morphia - mongodb

I have two model classes. One is Company.java, another is HumanResource.java.
Company.java
#Entity("companies")
public class Company {
#Id
private ObjectId id = new ObjectId();
private String companyName;
private String emailAddress;
private String pictureUrl;
#Reference
private List<HumanResource> humanResources;
...
HumanResource.java
#Entity("humanresources")
public class HumanResource {
#Id
private ObjectId id = new ObjectId();
private String firstName;
private String lastName;
private String emailAddress;
#Reference
private Company company;
...
What I want to achieve is when I save a list of companies to datastore, related list of human resources documents should be inserted automatically.
In addition, I declared
#Id
private ObjectId id = new ObjectId();
in every model class. Is it a good way or should I change it ?

Morphia will not call save() on those references. You must call save() on the instances you want to persist. You can pass in a list of instances so you needn't loop, necessarily, but each instance needs to get passed in explicitly.

Related

Spring MongoDB: Auditing one-to-many relation subdocument

I am currently working on a self-taught project, thus I am a beginner in MongoDB and I am struggling to audit a subdocument in an one-to-many relation. For some reason none of the new records inserted in this collection is being audited, although audit is working fine for all the other collections.
Below is the structure of the collections in my project:
User document is the main Document - auditing ok
Provider is an embedded subdocument in User (One-to-One) - auditing ok
Address is an embedded set of documents in Provider (One-to-Many) auditing fail
public class User extends Audit<String>{
#Id
private String id;
private String email;
private String firstName;
private String lastName;
private String salt;
private String password;
private String role;
private Boolean isVerified;
private String userTempCode;
private LocalDateTime deactivationDate;
private Provider provider; // This subdocument gets audited no problem
...
public class Provider extends Audit<ObjectId>{
private ObjectId id = new ObjectId();
private LocalDate dob;
private String phone;
private Double price;
private Object geoLocation;
private Set<WeekDays> days;
private Set<TimeRange> hours;
private Set<Address> addresses; // Here is where I am having trouble, the createdBy, createdDate and so on, are not working
private String userId;
private LocalDateTime deactivationDate;
private Set<Reviews> ratings;
....
public class Address extends Audit<ObjectId>{
#Id
private ObjectId id = new ObjectId();
private String street;
private String street2;
private String city;
private String province;
private String country;
private String postalCode;
...
//Below My Audit class inherited by all documents
#Data
public abstract class Audit<T> implements Persistable<T> {
#CreatedBy
private String createdBy;
#CreatedDate
private LocalDateTime createdDate;
#LastModifiedBy
private String lastModifiedBy;
#LastModifiedDate
private LocalDateTime lastModifiedDate;
#Version
public Integer version;
}
So, why is my Set< Address> not being audited whereas the other documents are ok, am I missing something here?
Thank you!

How to update few fields in mongodb by using MongoRepository?

I have a User POJO having fields:
#Id
private String _id;
private String phone;
private String email;
private String password;
private String userName;
private String dob;
private String gender;
private String city;
private String pincode;
private String status;
private String validUpto;
private List<String> userRole;
private String persona;
I saved all the fields in MongoDB (document).
Now I want to update only few fields like city, Pincode.
I also refer this question, but it is not giving the answer via MongoRepository.
is there any way we can update only few fields via MongoRepository instead of MongoTemplate.
The repository doesn't provide an 'update' operation only .save(object);
But you can update it by retrieving the Object from the repository, change the relevant fields. Afterwards, you save the updated object to the repository.
Which will get you the desired result of 'updating'.
Spring-boot/SpringRepository example.
#Autowired
UserRepository userRepository;
#Test
public void testUpdateUser() throws Exception {
User foundUser = userRepository.findById("1");
foundUser.setCity("Helsinki");
// foundUser.setOtherFields("new values");
userRepository.save(foundUser); // Will 'update' but it essentially replaces the entity in database
}

how to create an id within the embedded document using mongoDB and spring data

im trying to set a id within embedded document. in the next level in mongoDB, using spring data.
lets say i have a User document and each user has multiple Session (One-to-many), and i like to get an auto generate and unique id for the sessions. how would I do that?. I have tried to create the below entities for User & Session, but the id at session is always null!, please help
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document
public class User {
#Id
private String id;
private String emailId;
private String firstName;
private String lastName;
private ArrayList<Session> sessions;
}
public class Session {
#Id // i like to make this id auto generated and unique
private String id;
private String status;
private String title;
//assume all Args, Getters and setters are exists
You'd need to update this unique id manually for there doesn't seem to be an automated feature doing that in spring-data-mongodb.
Something like;
public Integer generateUniqueId() {
Session latestSession = sessionRepository.findTopOrderByIdDesc(); // latest session
return Optional.ofNullable(latestSession).map(Session::getId).orElse(-1) + 1;
}
where unique id is just an incrementing counter...
& set this value to the new Session before saving it;
newSession.set(generateUniqueId());
sessionRepository.save(newSession);
For more details, check here

Filtering a list in Objectify using Ref

How do i filter a list of an entity in Objectify which has Ref to another entity. The list should be filtered out based on a String field in the Ref entity.
public class AccountEntity extends BaseEntity {
#Index
private String accountName;
private String accountNo;
private String description;
private Integer displayOrderNo;
private Boolean contra = false;
private AccountingAccountType accountType;
#Index
private Ref<AccountGroupEntity> accountGroup;
#Ignore
private List<AccountEntryEntity> accountLedgerEntries;
public AccountEntity() {
}
this is ref entity
filter code
A ref is a key, so you can filter the key by passing in either a Key, Key<>, Ref<> or #Entity pojo.
You cannot however filter on a property of the entity that the key points to. To do this you'll need to denormalise that property into a separate indexed list in this entity, or create a lookup entity, similar to a join table.

How to map existing JPA entities to PicketLink

I am trying to migrate a Seam 2 app to CDI and use PicketLink for security. After all the reading and researching, it seems like all the examples are having one to one mapping between PicketLink model and the backend entity. e.g. Account to AccountEntity, Partition to PartitionEntity. Since I already have entities in place representing identity model, I am stuck on trying to map them to PicketLink. Here is what I have:
#MappedSuperClass
public class ModelEntityBase implement Serializable {
#Id #Generated
Long id;
Date creationDate;
}
#Entity
public Account extends ModelEntityBase {
String username;
String passwordHash;
#OneToOne(mappedBy = "account")
Person person;
}
#Entity
public Person extends ModelEntityBase {
String name;
String email;
#OneToOne
#JoinColumn(name = "account_id")
Account account;
}
Two entities (plus a super class) representing a single identity model in PicketLink, e.g. stereo type User.
Based on this why IdentityType id is String not Long, I tried to add a new Entity in:
#Entity
#IdentityManaged(BaseIdentityType.class);
public class IdentityTypeEntity implement Serializble {
#Id #Identifier
private String id;
#OneToOne(optional = false, mappedBy = "identityType")
#OwnerReference
private Account account;
#IdentityClass
private String typeName;
#ManyToOne #OwnerReference
private PartitionEntity partition;
}
I've tried a few different ways with the annotation and model classes. But when using IdentityManager.add(myUserModel), I just can't get it to populate all the entities. Is this even possible?
Got help from Pedro (PicketLink Dev). Post the answer here to help others.
This is the model class I ended up using.
#IdentityStereotype(USER)
public class User extends AbstractAttributedType implements Account {
#AttributeProperty
private Account accountEntity;
#AttributeProperty
#StereotypeProperty(IDENTITY_USER_NAME)
#Unique
private String username;
#AttributeProperty
private boolean enabled;
#AttributeProperty
private Date createdDate;
#AttributeProperty
private Date expiryDate;
#AttributeProperty
private Partition partition;
// getter and setter omitted
}
And created a new entity to map to this model:
public class IdentityTypeEntity implements Serializable {
#Id
#Identifier
private String id;
#OneToOne(optional = false, mappedBy = "identityType",
cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#AttributeValue
// #NotNull
private HAccount accountEntity;
#IdentityClass
private String typeName;
#ManyToOne
#OwnerReference
private PartitionEntity partition;
#AttributeValue
private String username;
#AttributeValue
// #Transient
private boolean enabled;
#AttributeValue
private Date createdDate;
#AttributeValue
private Date expiryDate;
}
PL can map property with #AttributeProperty to entity property with #AttributeValue. But it can only map to one entity. Therefore there is no way to map, say User and its properties over to Account and Person. But you can have the entity (in my case accountEntity) in the model. I also have to duplicate a few fields in the new IdentityTypeEntity and my existing Account entity (username, eanbled, createdDate) because PL requires these. Use a #PrePersist and similar to sync them.