Example of Hibernate OGM with MongoDB

最近在研究 NoSQL 原本是打算使用 Cassandra,

可惜目前版本的 Hibernate OGM 似乎不並支援,

發這篇文章的時間目前 Hibernate 的版本為 hibernate-ogm-4.1.0.Beta5-dist ,

似乎要等到 hibernate-ogm-4.2.0 才有支援,

所以只好改用 MongoDB,

這兩套資料庫並沒有哪套比較好或不好,

只是單純因為使用的類型對我來說  Cassandra 比較符合我的需要,

Hibernate OGM 這個 Framework 似乎不大穩定,

許多 API 的介面不同版本也有差異,

所以如果你用的是不同版本而無法編譯也不用太訝異,

網路上似乎找不到介紹如何使用 Hibernate OGM 搭配 MongoDB 的文章,

(也可能是我沒用心找…)

自己試了一個下午總算弄懂要如何用了,

貼上來給想要嘗試的朋友少走些冤枉路。

MongoDB : 2.4.9

Hibernate OGM : hibernate-ogm-4.1.0.Beta5

範例檔 使用 IDE 為 Eclipse:

https://mega.co.nz/#!ysQWwQLA!7d0YAlqDW_4t9piH5OOMztmwBn9NhU9LUHTuxWtuxRs

下面貼出比較重要的幾個檔案內容

hibernate-cfg.xml

如果 MongoDB 有設定帳號密碼請自行增加 hibernate.ogm.datastore.username, hibernate.ogm.datastore.password 這兩個屬性, 其中

hibernate.ogm.datastore.databas 為資料庫名稱

hibernate.ogm.datastore.host      為 MongoDB 主機 IP (Ubuntu 安裝好預設只能本機連線,需修改 /etc/mongodb.conf 將 bind_ip = 127.0.0.1 改成自己主機 IP)

hibernate.ogm.datastore.port      為 MongoDB 主機 Port

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>  
  <session-factory>
	<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
    <property name="hibernate.current_session_context_class">thread</property>
    <property name="hibernate.ogm.datastore.provider">MONGODB</property>
    <property name="hibernate.ogm.datastore.database">mydb</property>
    <property name="hibernate.ogm.datastore.host">127.0.0.1</property>
    <property name="hibernate.ogm.datastore.port">27017</property>
    <property name="hibernate.ogm.datastore.grid_dialect">org.hibernate.ogm.datastore.mongodb.MongoDBDialect</property>
    <property name="hibernate.search.lucene_version">LUCENE_30</property>
    <property name="hibernate.search.default.directory_provider">filesystem</property>
    <property name="hibernate.search.default.indexBase">./Indexes</property>
    <property name="hibernate.search.default.locking_strategy">single</property>
    <mapping resource="hibernate-contact.hbm.xml"/>
  </session-factory>
</hibernate-configuration>

hibernate-contact.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="User" table="Users">
  <id  name="id" type="java.lang.String" >
      <column name="id" length="36" /> 
      <generator class="uuid2" />
  </id>
  <property name="name" type="java.lang.String">
      <column name="name"></column>
  </property>
  </class>
  </hibernate-mapping>

Main.java

import java.io.File;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.ogm.cfg.OgmConfiguration;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.query.DatabaseRetrievalMethod;
import org.hibernate.search.query.ObjectLookupMethod;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.hibernate.service.ServiceRegistry;

public class Main {
	
	public static void main(String[] args) {
		File file = new File("hibernate-cfg.xml");
		OgmConfiguration cfgogm = new OgmConfiguration();
		cfgogm.configure(file);
		StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(cfgogm.getProperties());
		ServiceRegistry sr = builder.build();
        SessionFactory sessionFactory = cfgogm.buildSessionFactory(sr);
        Session session= sessionFactory.openSession();
        Transaction tx= session.beginTransaction();
        User user = new User();
        user.setName("SnowWolf725");
        session.save(user);
        tx.commit();
        searchByName(session, "SnowWolf725");
        session.close();
        System.exit(0);
	}

	private static void searchByName(Session session, String name) {
		FullTextSession fulltextsession = Search.getFullTextSession(session); 
        QueryBuilder querybuilder = fulltextsession.getSearchFactory().buildQueryBuilder().forEntity(User.class).get();
		org.apache.lucene.search.Query lucenequery = querybuilder.keyword().onField("name").matching(name).createQuery();     
        org.hibernate.search.FullTextQuery fulltextquery = fulltextsession.createFullTextQuery( lucenequery,User.class );
        fulltextquery.initializeObjectsWith(ObjectLookupMethod.SKIP, DatabaseRetrievalMethod.FIND_BY_ID);
        List<?> result=fulltextquery.list();
        System.out.println(result.size() + " records");
        fulltextsession.clear();
	}
}

User.java

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.DocumentId;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.Store;


@Entity
@Indexed
public class User {
   @Id  
   @Column(length = 32, nullable = false)  
   @GeneratedValue(generator = "uuid2" )
   @GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator" )
   @DocumentId
   private String id;
   
   @Field(index= Index.YES,analyze = Analyze.NO,store = Store.NO)
   private String name;
   
   public String getId() { return id; }
   public void setId(String id) { this.id = id; }
   
   public String getName() { return name; }
   public void setName(String name) { this.name = name; }
}