MongoDB自動增長id實現、自定義函式呼叫、與Spring整合
阿新 • • 發佈:2018-12-24
昨天同事問實現MongoDB主鍵自動增長有什麼好的辦法,雖然喜歡MongoDB客戶端驅動程式自動生成的id,不過還是來測試了一下,僅僅是測試哦
廢話少說
1、建立專案,新增依賴
<dependencies> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.7.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.1.7.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </dependency> </dependencies>
2、使用了spring-data-mongo,所以建立封裝資料的演示類
3、建立資源配置檔案app.propertiespublic class User { private long id; private String name; public User(long id, String name) { this.id = id; this.name = name; } public long getId() { return id; } public String getName() { return name; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } }</span>
mongodb.host=localhost
mongodb.port=27017
4、spring配置檔案
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mongo="http://www.springframework.org/schema/data/mongo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd"> <context:property-placeholder location="classpath:app.properties"/> <mongo:mongo-client id="mongoClient" host="${mongodb.host}" port="${mongodb.port}"/> <mongo:db-factory id="dbFactory" dbname="script" mongo-ref="mongoClient"/> <mongo:template id="mongoTemplate" db-factory-ref="dbFactory" converter-ref="mappingMongoConverter"/> <bean id="dbRefResolver" class="org.springframework.data.mongodb.core.convert.DefaultDbRefResolver"> <constructor-arg ref="dbFactory"/> </bean> <bean id="mongoMappingContext" class="org.springframework.data.mongodb.core.mapping.MongoMappingContext"/> <bean id="defaultMongoTypeMapper" class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper"> <constructor-arg name="typeKey"> <null/> </constructor-arg> </bean> <bean id="mappingMongoConverter" class="org.springframework.data.mongodb.core.convert.MappingMongoConverter"> <constructor-arg name="dbRefResolver" ref="dbRefResolver"/> <constructor-arg name="mappingContext" ref="mongoMappingContext"/> <property name="typeMapper" ref="defaultMongoTypeMapper"/> </bean> </beans>
5、測試程式碼
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.ScriptOperations;
import org.springframework.data.mongodb.core.script.ExecutableMongoScript;
import org.springframework.data.mongodb.core.script.NamedMongoScript;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;
import static org.springframework.data.mongodb.core.query.Update.update;
/**
* (1) Test an auto-increment pattern for the _id field.
*
* (2) Test MongoDB Script and Spring Script Operations.
*
* Created by gaofu on 16-2-5.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:beans.xml")
public class AutoIncrementIdAndScriptTest {
@Autowired
private MongoTemplate template;
@Before
public void setUp() throws Exception {
ScriptOperations scriptOps = template.scriptOps();
// 將JavaScript函式儲存到MongoDB server,以便直接在客戶端呼叫
scriptOps.register(new NamedMongoScript("getNextSequence", "function(name){var ret=db.counters.findAndModify({query:{_id:name},update:{$inc:{seq:NumberLong(1)}},new:true});return ret.seq.floatApprox}"));
// scriptOps.register(new NamedMongoScript("getNextSequence", "function(name){var ret=db.counters.findAndModify({query:{_id:name},update:{$inc:{seq:1}},new:true});return ret.seq}")); // 這樣就會把seq變成雙精度浮點型
template.upsert(query(where("_id").is("userid")), update("seq", 0L), "counters");
}
@Test
public void testClientScript() {
final String origin = "Hello World";
String script = "function(x){return x + \".\"}";
ExecutableMongoScript mongoScript = new ExecutableMongoScript(script);
ScriptOperations scriptOps = template.scriptOps();
Object result1 = scriptOps.execute(mongoScript, origin);
// Spring使用String.format()方法對字串進行了處理
// System.out.println(result1);
assertEquals(String.format("'%s'", origin) + '.', result1);
Object mongoEval = template.getDb().eval(script, origin);
// System.out.println(mongoEval);
assertEquals(origin + ".", mongoEval);
Object result2 = scriptOps.execute(mongoScript, 3);
assertEquals("3.", result2);
}
@Test
public void testAutoIncrementIdAndStoredScript() {
ScriptOperations scriptOps = template.scriptOps();
boolean exists = scriptOps.exists("getNextSequence");
assertTrue(exists);
// JavaScript返回的總是雙精度浮點型數字,所以需要轉換
User jack = new User(((Number) scriptOps.call("getNextSequence", "userid")).longValue(), "Jack");
User rose = new User(((Number) scriptOps.call("getNextSequence", "userid")).longValue(), "Rose");
template.insert(jack);
template.insert(rose);
assertEquals(1, jack.getId());
assertEquals(2, rose.getId());
DB db = template.getDb();
Object eval = db.eval("getNextSequence('userid')");
// JavaScript返回的總是雙精度浮點型數字
assertEquals(3.0d, eval);
}
/**
* 註釋掉此方法可以檢視資料庫中的集合資料。
*/
@After
public void tearDown() throws Exception {
template.dropCollection("counters");
template.dropCollection(User.class);
template.getCollection("system.js").remove(new BasicDBObject("_id", "getNextSequence"));
}
}
6、spring需要日誌輸出,簡單配置如下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
<appender name="default" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %40.40c:%4L - %m%n"/>
</layout>
</appender>
<root>
<level value="info"/>
<appender-ref ref="default"/>
</root>
</log4j:configuration>
備註:
(1)別忘了在本地啟動MongoDB伺服器。
(2)如果比較懶,想親自動手測試,又懶得拷貝程式碼,可以下載原始碼。