公司對於mongodb的使用

1.pom文件添加對mongodb的倚賴

複製代碼
<dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
        <version>3.2.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-mongodb</artifactId>
        <version>${data.mongodb}</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-mongodb-cross-store</artifactId>
        <version>${data.mongodb}</version>
    </dependency>
    <dependency>
       <groupId>org.springframework.data</groupId>
       <artifactId>spring-data-mongodb-log4j</artifactId>
       <version>${data.mongodb}</version>
    </dependency>
複製代碼

2.applicationContext.xml

複製代碼
<?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"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
    <!-- 掃描 -->
    <context:component-scan base-package="cn.com.xxx.mongodb"/>
    
    <!-- 引入mongodb的相關配置 -->
    <import resource="classpath:spring-mongodb.xml"/>
    
</beans>
複製代碼

4.mongodb.properties

複製代碼
#數據庫名稱
mongo.dbname = test
#用戶名
mongo.username = root
mongo.credentials=root:000000@test
#密碼
mongo.password = 000000
#主機
mongo.host = 127.0.0.1
#端口號
mongo.port= 27017
#一個線程變爲可用的最大阻塞數
mongo.connectionsPerHost= 8
#線程隊列數,它以上面connectionsPerHost值相乘的結果就是線程隊列最大值
mongo.threadsAllowedToBlockForConnectionMultiplier= 4
#連接超時時間(毫秒)
mongo.connectTimeout= 1500
#最大等待時間
mongo.maxWaitTime= 1500
#自動重連
mongo.autoConnectRetry= true
#scoket保持活動
mongo.socketKeepAlive= true
#scoket超時時間
mongo.socketTimeout=1500
#讀寫分離
mongo.slaveOk=true
複製代碼

 

3.spring-mongodb.xml

複製代碼
<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/context   
          http://www.springframework.org/schema/context/spring-context-3.0.xsd   
          http://www.springframework.org/schema/data/mongo   
          http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
          http://www.springframework.org/schema/aop 
          http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
          http://www.springframework.org/schema/beans   
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- 加載mongodb的屬性配置文件 -->
    <context:property-placeholder location="classpath:mongodb.properties" />

    <!-- 定義mongo對象,對應的是mongodb官方jar包中的Mongo,replica-set設置集羣副本的ip地址和端口 -->
<!--     
    <mongo:mongo id="mongo" host="${mongo.host}" port="${mongo.port}" >
    
    <mongo:client-options 
        connections-per-host="${mongo.connectionsPerHost}" 
        threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}" 
        connect-timeout="${mongo.connectTimeout}" 
        max-wait-time="${mongo.maxWaitTime}" 
        auto-connect-retry="${mongo.autoConnectRetry}" 
        socket-keep-alive="${mongo.socketKeepAlive}" 
        socket-timeout="${mongo.socketTimeout}" 
        slave-ok="${mongo.slaveOk}" 
        write-number="1" 
        write-timeout="0" 
        write-fsync="true"/> 
    </mongo:mongo> 
    -->
  <!-- 我們使用的mongodb的版本是3.X,所以在構造這段話的時候要根據 Mongo  類的構造函數來構造,不同版本可能會造成構造函數的不同-->
    <mongo:mongo-client id="mongo" host="${mongo.host}" port="${mongo.port}" credentials="${mongo.credentials}">
    
        <mongo:client-options 
        connections-per-host="${mongo.connectionsPerHost}" 
        threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}" 
        connect-timeout="${mongo.connectTimeout}" 
        max-wait-time="${mongo.maxWaitTime}" 
        socket-keep-alive="${mongo.socketKeepAlive}" 
        socket-timeout="${mongo.socketTimeout}"        
       /> 
    </mongo:mongo-client>

    <!-- 用戶驗證 -->
    <bean id="userCredentials" class="org.springframework.data.authentication.UserCredentials">
        <constructor-arg name="username" value="${mongo.username}" />
        <constructor-arg name="password" value="${mongo.password}" />
    </bean>
    <!-- mongo的工廠,通過它來取得mongo實例,dbname爲mongodb的數據庫名,沒有的話會自動創建 -->
    <bean id="mongoDbFactory"
        class="org.springframework.data.mongodb.core.SimpleMongoDbFactory">
        <constructor-arg ref="mongo" />
        <constructor-arg value="${mongo.dbname}" />
        <!-- <constructor-arg ref="userCredentials" /> -->
    </bean>

    <bean id="mappingContext"
        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>

    <!-- collection的映射 -->
    <bean id="mappingMongoConverter"
        class="org.springframework.data.mongodb.core.convert.MappingMongoConverter">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
        <constructor-arg name="mappingContext" ref="mappingContext" />
        <property name="typeMapper" ref="defaultMongoTypeMapper" />
    </bean>

    <!-- mongodb的主要操作對象,所有對mongodb的增刪改查的操作都是通過它完成 -->
    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
        <constructor-arg name="mongoConverter" ref="mappingMongoConverter" />
    </bean>
    <bean id="audience" class="cn.com.xxx.mongodb.aop.Audience"/>

    <aop:config proxy-target-class="true">
        <aop:aspect ref="audience">
            <aop:pointcut id="performance" expression="execution(* cn.com.mongodb.service.impl.*.*(..))"/>
            
            <aop:before pointcut-ref="performance" method="takeSeats"/>
            <aop:before pointcut-ref="performance" method="turnOffCellPhones"/>
            <aop:around pointcut-ref="performance" method="around"/>
            <aop:after-returning pointcut-ref="performance" method="applaud"/>
            <aop:after-throwing pointcut-ref="performance" method="demandRefund"/>
            <aop:after pointcut-ref="performance" method="after"/>
        </aop:aspect>
    </aop:config>
</beans>
複製代碼

5.爲了使javabean對象與mongodb對象相互轉化,本人借鑑別人的例子,稍加改動, 主要是應對數據庫表字段的命名是含 _ 的這種方式,首先需要約定在生成java pojo的時候,每個字段上面要加上@Field註解(方便利用反射來讓兩者之間相互轉換)

複製代碼
@Document(collection="item_info")
public class ItemInfo implements Serializable {

    private static final long serialVersionUID = 1L;
    private Oid _id;
    @Field(value="item_id")
    private String itemId;
    @Field(value="item_name")
    private String itemName;
    @Field(value="price")
    private Double price;
    @Field(value="desc")
    private String desc;

    public Oid get_id() {
        return _id;
    }

    public void set_id(Oid _id) {
        this._id = _id;
    }

    public String getItemId() {
        return itemId;
    }

    public void setItemId(String itemId) {
        this.itemId = itemId;
    }

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    @Override
    public String toString() {
        return "ItemInfo [_id=" + _id + ", itemId=" + itemId + ", itemName="
                + itemName + ", price=" + price + ", desc=" + desc + "]";
    }
複製代碼

實現java對象與DBObject對象之間的相互轉化

複製代碼
public class BeanUtil {


      /**
       * 把實體bean對象轉換成DBObject
       * @param bean
       * @return
       * @throws IllegalArgumentException
       * @throws IllegalAccessException
       */
      public static <T> DBObject bean2DBObject(T bean) throws IllegalArgumentException,
          IllegalAccessException {
        if (bean == null) {
          return null;
        }
        DBObject dbObject = new BasicDBObject();
        // 獲取對象對應類中的所有屬性域
        Field[] fields = bean.getClass().getDeclaredFields();
        
        // 獲取所有註解
        for (Field field : fields) {
            org.springframework.data.mongodb.core.mapping.Field anno = field.getAnnotation(org.springframework.data.mongodb.core.mapping.Field.class);
          // 獲取屬性名
          String varName = field.getName();
          
          if("serialVersionUID".equals(varName) || "_id".equals(varName)){
              continue;
          }
          
          // 獲取註解的值
          varName = anno.value();
          // 修改訪問控制權限
          boolean accessFlag = field.isAccessible();
          if (!accessFlag) {
            field.setAccessible(true);
          }
          Object param = field.get(bean);
          if (param == null) {
            continue;
          } else if (param instanceof Integer) {//判斷變量的類型
            int value = ((Integer) param).intValue();
            dbObject.put(varName, value);
          } else if (param instanceof String) {
            String value = (String) param;
            dbObject.put(varName, value);
          } else if (param instanceof Double) {
            double value = ((Double) param).doubleValue();
            dbObject.put(varName, value);
          } else if (param instanceof Float) {
            float value = ((Float) param).floatValue();
            dbObject.put(varName, value);
          } else if (param instanceof Long) {
            long value = ((Long) param).longValue();
            dbObject.put(varName, value);
          } else if (param instanceof Boolean) {
            boolean value = ((Boolean) param).booleanValue();
            dbObject.put(varName, value);
          } else if (param instanceof Date) {
            Date value = (Date) param;
            dbObject.put(varName, value);
          }
          // 恢復訪問控制權限
          field.setAccessible(accessFlag);
        }
        
        return dbObject;
      }

      /**
       * 把DBObject轉換成bean對象
       * @param dbObject
       * @param bean
       * @return
       * @throws IllegalAccessException
       * @throws InvocationTargetException
       * @throws NoSuchMethodException
       */
      public static <T> T dbObject2Bean(DBObject dbObject, T bean) throws IllegalAccessException,
          InvocationTargetException, NoSuchMethodException {
        if (bean == null) {
          return null;
        }
        Field[] fields = bean.getClass().getDeclaredFields();
        for (Field field : fields) {
          String varName = field.getName();
          org.springframework.data.mongodb.core.mapping.Field anno = field.getAnnotation(org.springframework.data.mongodb.core.mapping.Field.class);
          if("serialVersionUID".equals(varName) || "_id".equals(varName)){
              continue;
          }
          
          String fieldName = anno.value();
          Object object = dbObject.get(fieldName);
          if (object != null) {
            BeanUtils.setProperty(bean, varName, object);
          }
        }
        return bean;
      }
}
複製代碼

好了,準備工作就做好了

相應的Service與實現方法

複製代碼
public interface ItemInfoService {

    // 查詢
    public List<ItemInfo> getItemInfo(JSONObject json) throws Exception;
    
    // 保存
    public int save(ItemInfo itemInfo) throws Exception;
    
    // 更新
    public void update(ItemInfo intemInfo) throws Exception;
}
複製代碼
複製代碼
@Service(value="itemInfoService")
public class ItemInfoServiceImpl implements ItemInfoService {

    @Autowired
    private MongoTemplate mongoTemplate;
    private final static String COLLECTION_NAME = "item_info"; 
    
    @Override
    @SuppressWarnings("static-access")
    public List<ItemInfo> getItemInfo(JSONObject json) throws Exception{
        List<ItemInfo> list = new ArrayList<ItemInfo>();
        // 判斷查詢的json中傳遞過來的參數
        DBObject query = new BasicDBObject();
        // item_id,item_name,price,desc
        if(json.has("item_id")){
            
            query.put("item_id", json.getString("item_id"));
        }else if(json.has("item_name")){
            query.put("item_name", json.getString("item_name"));
        }
        
        DBCursor results = mongoTemplate.getCollection("item_info").find(query);
        if(null != results){
            Iterator<DBObject> iterator = results.iterator();
            while(iterator.hasNext()){
                //Document doc = (Document) iterator.next();
                BasicDBObject obj = (BasicDBObject) iterator.next();
                //System.out.println(obj.toJson());
                // json 字符串
                String objStr = obj.toString();
                //JSONObject itemInfoJson = new JSONObject().fromObject(objStr);
                //itemInfoJson.put("_id", itemInfoJson.getJSONObject("_id").getString("$oid"));
                ItemInfo itemInfo = new ItemInfo();
                itemInfo = BeanUtil.dbObject2Bean(obj, itemInfo);
                list.add(itemInfo);
            }
        }
        
        
        return list;
    }

    @Override
    public int save(ItemInfo itemInfo) throws Exception {
        itemInfo.setDesc("1111");
        itemInfo.setItemId("i1234567890123");
        itemInfo.setItemName("item_name_xx");
        itemInfo.setPrice(110.0);
        
        DBCollection collection = this.mongoTemplate.getCollection("item_info");
        int result = 0;
        DBObject iteminfoObj = BeanUtil.bean2DBObject(itemInfo);
        
        //iteminfoObj.removeField("serialVersionUID");
        //result = collection.insert(iteminfoObj).getN();
        WriteResult writeResult = collection.save(iteminfoObj);
        result = writeResult.getN();
        return result;
    }

    @Override
    public void update(ItemInfo intemInfo) throws Exception {
        
        DBCollection collection = this.mongoTemplate.getCollection(COLLECTION_NAME);
        ItemInfo queryItemInfo = new ItemInfo();
        queryItemInfo.setItemId(intemInfo.getItemId());
        DBObject itemInfoObj = BeanUtil.bean2DBObject(intemInfo);
        DBObject query =  BeanUtil.bean2DBObject(queryItemInfo);
        collection.update(query, itemInfoObj);
    }

    

}
複製代碼

junit test

複製代碼
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class ItemInfoServiceTest {

    @Autowired
    private ItemInfoService itemInfoService;
    
    @Ignore
    @Test
    public void testSave(){
        ItemInfo itemInfo = new ItemInfo();
        try {
            this.itemInfoService.save(itemInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    @Ignore
    @Test
    public void testGetItemInfo(){
        List<ItemInfo> list = new ArrayList<ItemInfo>();
        JSONObject json = new JSONObject();
        //json.put("item_id", "47a09d51-bf24-442b-9076-4701dcb614b9");
        json.put("item_id", "i1234567890123");
        try {
            list = this.itemInfoService.getItemInfo(json);
            if(null != list && list.size() > 0){
                //System.out.println(list.get(0).toString());
                for (ItemInfo itemInfo : list) {
                    //itemInfo.setItemName("======");
                    this.itemInfoService.getItemInfo(json);
                }
            }
            System.out.println(1 / 0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    @Test
    public void testUpdate(){
        JSONObject json = new JSONObject();
        //json.put("item_id", "47a09d51-bf24-442b-9076-4701dcb614b9");
        json.put("item_id", "i1234567890123");
        List<ItemInfo> list = new ArrayList<ItemInfo>();
        try {
            list = this.itemInfoService.getItemInfo(json);
            
            if(null != list && list.size() > 0){
                for (ItemInfo itemInfo : list) {
                    
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}




三:附加說明(具體的一些配置的值)

spring中配置MongoDB有兩種方式:註解方式和配置文件方式

1、註解方式

配置類要繼承AbstractMongoConfiguration類,重寫mongo()和mongoTemplate()方法

import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.data.document.mongodb.MongoTemplate;  
import org.springframework.data.document.mongodb.config.AbstractMongoConfiguration;  
import com.mongodb.Mongo;  
/** 
* Spring MongoDB configuration file 
*/  
@Configuration  
public class SpringMongoConfig extends AbstractMongoConfiguration {  
    @Override  
    public @Bean Mongo mongo() throws Exception {  
        return new Mongo("localhost");  
    }  
    @Override  
    public @Bean MongoTemplate mongoTemplate() throws Exception {  
        return new MongoTemplate(mongo(),"mydbname","myCollection");  
    }  
}  
調用Spring Mongo配置,只需要在需要使用的類中調用AnnotationConfigApplicationContext,傳入剛纔配置好的SpringMongoConfig類即可。


ApplicationContext ac = new AnnotationConfigApplicationContext(SpringMongoConfig.class);  
MongoOperations mo = (MongoOperations)ac.getBean("mongoTemplate");  
至此便可對MongoDB進行操作了


2、配置文件的方式

<?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:mongo="http://www.springframework.org/schema/data/mongo"  
    xsi:schemaLocation=
        "http://www.springframework.org/schema/data/mongo  
        http://www.springframework.org/schema/data/mongo/spring-mongo.xsd  
        http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans.xsd">  
      
    <!-- 定義mongo對象,對應的是mongodb官方jar包中的Mongo,replica-set設置集羣副本的ip地址和端口 -->  
    <mongo:mongo id="mongo" replica-set="IP:端口號">  
        <!-- 一些連接屬性的設置 -->      
        <mongo:options  
             connections-per-host="最大連接數"  
             threads-allowed-to-block-for-connection-multiplier="最大阻塞線程數"  
             max-wait-time="最大等待時間"  
             connect-timeout="連接超時時間"
             socket-keep-alive="是否保持長連接" 
         />          
    </mongo:mongo>  
  
    <!-- mongo的工廠,通過它來取得mongo實例,dbname爲mongodb的數據庫名,沒有的話會自動創建 -->  
    <mongo:db-factory dbname="mongo中數據名稱" mongo-ref="mongo"/>  
  
    <!-- mongodb的主要操作對象,所有對mongodb的增刪改查的操作都是通過它完成 -->  
    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">  
      <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>  
    </bean>  
      
    <!-- 映射轉換器,掃描base-package目錄下的文件,根據註釋,把它們作爲mongodb的一個collection的映射 -->  
    <mongo:mapping-converter base-package="collection映射所在包名" />  
      
    <!-- mongodb bean的倉庫目錄,會自動掃描擴展了MongoRepository接口的接口進行注入 -->  
    <mongo:repositories base-package="Repository所在包名"/>  
  
</beans>  


補充各個參數說明:

#對mongo實例來說,每個host允許鏈接的最大鏈接數,這些鏈接空閒時會放入池中,如果鏈接被耗盡,任何請求鏈接的操作會被阻塞等待鏈接可用,推薦配置10
connectionsPerHost=10
#當鏈接空閒時,空閒線程池中最大鏈接數
minPoolsSize=5
#此參數跟connectionsPerHost的乘機爲一個線程變爲可用的最大阻塞數,超過此乘機數之後的所有線程將及時獲取一個異常.eg.connectionsPerHost=10 and threadsAllowedToBlockForConnectionMultiplier=5,最多50個線程等級一個鏈接,推薦配置爲5
threadsAllowedToBlockForConnectionMultiplier=5
#一個線程等待鏈接可用的最大等待毫秒數,0表示不等待,負數表示等待時間不確定,推薦配置120000
maxWaitTime=120000
#鏈接超時的毫秒數,0表示不超時,此參數只用在新建一個新鏈接時,推薦配置10,000.
connectTimeout=10000
#此參數表示socket I/O讀寫超時時間,推薦爲不超時,即 0    Socket.setSoTimeout(int)
socketTimeout=0
#該標誌用於控制socket保持活動的功能,通過防火牆保持連接活着
socketKeepAlive=false
#true:假如鏈接不能建立時,驅動將重試相同的server,有最大的重試次數,默認爲15次,這樣可以避免一些server因爲一些阻塞操作零時down而驅動拋出異常,這個對平滑過度到一個新的master,也是很有用的,注意:當集羣爲複製集時,驅動將在這段時間裏,嘗試鏈接到舊的master上,而不會馬上鍊接到新master上
#false 當在進行socket讀寫時,不會阻止異常拋出,驅動已經有自動重建破壞鏈接和重試讀操作. 推薦配置false
autoConnectRetry=false
#重新打開鏈接到相同server的最大毫秒數,推薦配置爲0,如果 autoConnectRetry=true,表示時間爲15s
#com.jd.mongodbclient2.mongo.JDClientMongo.maxAutoConnectRetryTime=false
#表示當沒有手動關閉遊標時,是否有一個自動釋放遊標對象的方法,如果你總是很小心的關閉遊標,則可以將其設爲false 推薦配置true

#com.jd.mongodbclient2.mongo.JDClientMongo.cursorFinalizerEnabled=true

#安全模式

com.jd.mongodbclient2.driver.MongoDBDriver.safe=true

#爲true表示讀寫分離

com.jd.mongodbclient2.driver.MongoDBDriver.slaveOk=false

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章