Working with MongoDB using Kundera
Join the DZone community and get the full member experience.
Join For FreeKundera – a JPA 2.0 (Java Persistence API) based ORM library was originally developed for Cassandra database. A support for Hbase was later added to it.
Those who are new to Kundera, should read this to get a basic idea. For impatient ones – Get started with Kundera in 5 minutes!
Kundera now supports MongoDB – a document-oriented database. Some salient features of MongoDB datamodel are:
- Documents are stored as “collections” in DBs.
- A document can be embedded into other document, and hence no join is needed for retrieving data. This makes database operations fast.
- Drivers are available for most of the popular programming languages.
Our Data Model
{ EMAIL: { “MESSAGE_ID” : “1″, “SUBJECT” : “Please Join Meeting”, “BODY” : “Agenda: RFP discussion”, “FROM” : { “CONTACT_ID” : “a″, “FIRST_NAME” : “Amresh”, “LAST_NAME” : “Singh”, “EMAIL_ID” : “xamry@gmail.com” } “TO” : [ { “CONTACT_ID” : “b″, “FIRST_NAME” : “Vivek”, “LAST_NAME” : “Mishra”, “EMAIL_ID” : “mevivs@gmail.com” }, { “CONTACT_ID” : “c″, “FIRST_NAME” : “Saurabh”, “LAST_NAME” : “Singh”, “EMAIL_ID” : “saurabh@gmail.com” } ] } } { ATTACHMENT: { "ATTCHMENT_ID" : "aaa", "FILE_NAME" : "Agenda.doc", "FILE_TYPE" : "MS Word", "MESSAGE_ID" : "1" } { "ATTCHMENT_ID" : "bbb", "FILE_NAME" : "MOM_Last_Meeting.xls", "FILE_TYPE" : "MS Excel", "MESSAGE_ID" : "1" } { "ATTCHMENT_ID" : "ccc", "FILE_NAME" : "Client_Feedback.txt", "FILE_TYPE" : "Text", "MESSAGE_ID" : "1" } }
Environment Setup
Create Entity Classes
- Your entity classes should be annotated with @Entity and each fields should be annotated with @Column.
- Field corresponding to primary key should be annotated with @Id.
- In addition to this, your entity class should also be annotated with @Table, which is used by Kundera to determine the DB name and collection name.
- All embedded entity fields should be annotated with @Embedded or @ElementCollection. They are stored with the enclosing entity table
- All Relationships should be annotated with @OneToOne, @OneToMany, @ManyToOne or @ManyToMany. They are stored as separate collection and relationship is maintained via either Join Column or Join Table as the case may be.
Email Entity
import java.util.ArrayList; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name = "EMAIL", schema = "KunderaExamples@twingo") public class Email { @Id @Column(name="MESSAGE_ID") private String messageId; @Column(name = "SUBJECT") private String subject; @Column(name = "BODY") private String body; @Embedded private Contact from; @ElementCollection @CollectionTable(name = "TO") private List<Contact> to; @OneToMany (cascade={CascadeType.ALL}, fetch=FetchType.LAZY) @JoinColumn(name="MESSAGE_ID") private List<Attachment> attachments; //Getters, setters, constructors and utility methods omitted. }
Contact Embedded Object
import javax.persistence.Column; import javax.persistence.Embeddable; @Embeddable public class Contact { @Column(name = "CONTACT_ID") String contactId; @Column(name = "LAST_NAME") String lastName; @Column(name = "FIRST_NAME") String firstName; @Column(name = "EMAIL_ID") String emailId; //Getters, setters, constructors and utility methods omitted. }
Attachment Entity
import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "ATTACHMENT", schema = "KunderaExamples@twingo") public class Attachment { @Id @Column(name="ATTCHMENT_ID") private String attachmentId; @Column(name = "FILE_NAME") private String fileName; @Column(name = "FILE_TYPE") private String fileType; //Getters, setters, constructors and utility methods omitted. }
Create persistence.xml
Add the below entry in your persistence.xml file for letting kundera know the persistence unit name and details. This name is used in the application code for making connection with MongoDB and persisting entities.
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="2.0"> <persistence-unit name="twingo"> <provider>com.impetus.kundera.KunderaPersistence</provider> <properties> <property name="kundera.nodes" value="localhost" /> <property name="kundera.port" value="27017" /> <property name="kundera.keyspace" value="KunderaExamples" /> <property name="kundera.dialect" value="mongodb" /> <property name="kundera.client.lookup.class" value="com.impetus.client.mongodb.MongoDBClientFactory" /> <property name="kundera.cache.provider.class" value="com.impetus.kundera.cache.ehcache.EhCacheProvider" /> <property name="kundera.cache.config.resource" value="/ehcache-test.xml" /> </properties> </persistence-unit> </persistence>
Performing CRUD operations
- Create instance of EntityManagerFactory, providing Persistence Unit name as parameter.
- Perform database operation using JPA 2.0 API.
- Cleanup resources.
Insert a new entity:
Email email = new Email(); email.setMessageId("1"); email.setSubject("Please Join Meeting"); email.setBody("Agenda: RFP discussion"); email.setFrom(new Contact("a", "Amresh", "Singh", "xamry@gmail.com")); email.addTo(new Contact("b", "Vivek", "Mishra", "mevivs@gmail.com")); email.addTo(new Contact("c", "Saurabh", "Singh", "saurabh@gmail.com")); email.addAttachment(new Attachment("aaa", "Agenda.doc", "MS Word")); email.addAttachment(new Attachment("bbb", "MOM_Last_Meeting.xls", "MS Excel")); email.addAttachment(new Attachment("ccc", "Client_Feedback.txt", "Text")); EntityManagerFactory emf = Persistence.createEntityManagerFactory("twingo"); EntityManager em = emf.createEntityManager(); em.persist(email); em.close(); emf.close();
You can verify whether entity was successfully persisted from the mongodb shell:
amresh@ubuntu:/usr/local/mongodb$ ./bin/mongo MongoDB shell version: 1.8.1 connecting to: test > use KunderaExamples; switched to db KunderaExamples > show collections; ATTACHMENT EMAIL system.indexes > db.EMAIL.find(); { "_id" : "1", "MESSAGE_ID" : "1", "subject" : { "SUBJECT" : "Please Join Meeting" }, "body" : { "BODY" : "Agenda: RFP discussion" }, "to" : [ { "CONTACT_ID" : "b", "LAST_NAME" : "Mishra", "FIRST_NAME" : "Vivek", "EMAIL_ID" : "mevivs@gmail.com" }, { "CONTACT_ID" : "c", "LAST_NAME" : "Singh", "FIRST_NAME" : "Saurabh", "EMAIL_ID" : "saurabh@gmail.com" } ], "from" : { "CONTACT_ID" : "a", "LAST_NAME" : "Singh", "FIRST_NAME" : "Amresh", "EMAIL_ID" : "xamry@gmail.com" } } > db.ATTACHMENT.find(); { "_id" : "aaa", "ATTCHMENT_ID" : "aaa", "FILE_NAME" : "Agenda.doc", "FILE_TYPE" : "MS Word", "MESSAGE_ID" : "1" } { "_id" : "bbb", "ATTCHMENT_ID" : "bbb", "FILE_NAME" : "MOM_Last_Meeting.xls", "FILE_TYPE" : "MS Excel", "MESSAGE_ID" : "1" } { "_id" : "ccc", "ATTCHMENT_ID" : "ccc", "FILE_NAME" : "Client_Feedback.txt", "FILE_TYPE" : "Text", "MESSAGE_ID" : "1" } >
Update an existing entity:
Code for updating an entity is similar to the one used for inserting entity. You just need to set fields in the entity and persist it. It will be updated into MongoDB.
Find an entity:
Finding an entity means retrieving a single entity if you know the primary key. Here is the java code to accomplish this task:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("twingo"); EntityManager em = emf.createEntityManager(); Email email = em.find(Email.class, "1"); em.close(); emf.close();
Run a JPA Query:
Kundera supports JPA-QL. See below an example code that fetches all the emails from a collection.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("twingo"); //Get all emails EntityManager em = emf.createEntityManager(); Query q = em.createQuery("select e from Email e"); List<?> emails = q.getResultList(); em.close(); emf.close();
Delete an Entity:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("twingo"); EntityManager em = emf.createEntityManager(); Email email = em.find(Email.class, "1"); em.remove(email); em.close(); emf.close();
Conclusion
Kundera makes it easier to work with NoSQL databases like Cassandra, Hbase, MongoDB by supporting JPA. Programmers, as a result, need to write lesser lines of code, which is easy to understand and maintain. Another advantage is, you don’t need to rewrite your code in case you choose to change your database vendor (say, from MongoDB to Cassandra). The only thing you’ll require is to add a persistence unit entry into persistence.xml, and use that name into your application code.
Published at DZone with permission of Amresh Singh, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Alpha Testing Tutorial: A Comprehensive Guide With Best Practices
-
Mastering Go-Templates in Ansible With Jinja2
-
Step Into Serverless Computing
-
Replacing Apache Hive, Elasticsearch, and PostgreSQL With Apache Doris
Comments