MongoDB與Spring整合(支持事務)——SpringDataMongoDB


1.將MongoDB設置為復制集模式

  a.修改 mongod.cfg 文件,添加replSetName復制集名稱

#replication:
replication:
  replSetName: "rs0"

  b.在MongDB命令行輸入初始化添加 localhost:27017 節點

rs.initiate( {_id : "rs0",members: [ { _id: 0, host: "localhost:27017" } ]})

 

 

2.添加maven依賴

    <!-- mongo -->
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-mongodb</artifactId>
      <version>2.1.1.RELEASE</version>
    </dependency>

  注:a.支持事務MongoDB要4.0版本以上,使用復制集,單節點不支持

    b.Spring要 5.1.1.RELEASE 以上

    c.SpringDataMongoDB要 2.1.1.RELEASE 以上

    d.使用事務之前(@Transaction),數據庫、文檔、索引必須提前創建

 

 

3.書寫 spring-mongo.xml 及對應 mongo.properties

<?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:tx="http://www.springframework.org/schema/tx"
       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
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:property-placeholder location="classpath:mongo.properties"/>

    <!-- <mongo:mongo-client id="mongo-client" host="${mongo.host}" port="${mongo.port}"> -->
    <mongo:mongo-client id="mongo-client" replica-set="${mongo.replSet}">
        <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>

    <mongo:repositories base-package="com.wode.dao"/>

    <mongo:db-factory dbname="${mongo.db}" mongo-ref="mongo-client"/>

    <bean id="mongoTemplate"
          class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
    </bean>

    <bean id="mongoTransactionManager" class="org.springframework.data.mongodb.MongoTransactionManager">
        <constructor-arg name="dbFactory" ref="mongoDbFactory"/>
    </bean>

    <tx:annotation-driven transaction-manager="mongoTransactionManager" proxy-target-class="true"/>

</beans>
mongo.host=localhost
mongo.port=27017
mongo.replSet=localhost:27017
mongo.db=testmongo

#################連接池配置#################

#最大連接數
mongo.connectionsPerHost=8
#可被阻塞的線程數因子,默認值為5,如果connectionsPerHost配置為10,那么最多能阻塞50個線程,超過50個之后就會收到一個異常
mongo.threadsAllowedToBlockForConnectionMultiplier=4
#連接超時時間,默認值是0,就是不超時
mongo.connectTimeout=1000
#阻塞線程獲取連接的最長等待時間,默認120000 ms
mongo.maxWaitTime=1500
#keep alive標志,默認false
mongo.socketKeepAlive=true
#socket超時時間,默認值是0,就是不超時
mongo.socketTimeout=1500

 

 

4.創建實體類

public class BaseBean {

    @Id
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}
@Document
public class Cmdty extends BaseBean {

    private String cmdtyCode;
    private String cmdtyName;
    private List<Attr> attributes;
    @DBRef
    private Info info;

    public String getCmdtyCode() {
        return cmdtyCode;
    }

    public void setCmdtyCode(String cmdtyCode) {
        this.cmdtyCode = cmdtyCode;
    }

    public String getCmdtyName() {
        return cmdtyName;
    }

    public void setCmdtyName(String cmdtyName) {
        this.cmdtyName = cmdtyName;
    }

    public List<Attr> getAttributes() {
        return attributes;
    }

    public void setAttributes(List<Attr> attributes) {
        this.attributes = attributes;
    }

    public Info getInfo() {
        return info;
    }

    public void setInfo(Info info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "[Cmdty]: cmdtyCode[" + cmdtyCode + "], cmdtyName[" + cmdtyName + "], attributes[" + attributes + "], info[" + info + "]";
    }
}
public class Attr extends BaseBean {

    private String key;

    private String value;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "[Attr]: key[" + key + "], value[" + value + "]";
    }

}
@Document
public class Info extends BaseBean {

    private String color;

    private String style;

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getStyle() {
        return style;
    }

    public void setStyle(String style) {
        this.style = style;
    }

    @Override
    public String toString() {
        return "[Info]: color[" + color + "], style[" + style + "]";
    }
}

 

 

5.通過 MongoTemplate 的方式

  a.創建Dao

@Repository
public class TestDao {

    @Resource
    protected MongoTemplate mongoTemplate;
    private Class<Cmdty> clazz;

    @PostConstruct
    private void construct(){
        clazz = Cmdty.class;
    }

    //添加
    public Cmdty insert(Cmdty t) {
        return mongoTemplate.insert(t);
    }

    //保存
    public Cmdty save(Cmdty t) {
        return mongoTemplate.save(t);
    }

    //保存商品信息
    public Info saveInfo(Info t) {
        return mongoTemplate.save(t);
    }

    //修改
    public int update(Map<String, Object> filter, Map<String, Object> updater) {
        UpdateResult result = mongoTemplate.updateMulti(this.getQuery(filter), this.getUpdater(updater), this.clazz);
        return (int) result.getModifiedCount();
    }

    //刪除
    public long delete(Map<String, Object> filter) {
        DeleteResult result = mongoTemplate.remove(this.getQuery(filter), this.clazz);
        return result.getDeletedCount();
    }

    //存在
    public boolean exist(Map<String, Object> filter) {
        return mongoTemplate.exists(this.getQuery(filter), this.clazz);
    }

    //個數
    public long count(Map<String, Object> filter) {
        return mongoTemplate.count(this.getQuery(filter), this.clazz);
    }

    //查詢一個
    public Cmdty getObject(Map<String, Object> filter) {
        return mongoTemplate.findOne(this.getQuery(filter), this.clazz);
    }

    //查詢多個
    public List<Cmdty> getList(Map<String, Object> filter) {
        return mongoTemplate.find(this.getQuery(filter), this.clazz);
    }

    protected Query getQuery(Map<String, Object> filter){
        Query query = new Query();
        for(Map.Entry<String, Object> entry : filter.entrySet()){
            String key = entry.getKey();
            Object value = entry.getValue();
            switch (key){
                case "id":
                    query = query.addCriteria(Criteria.where("_id").is(value));
                    break;
                case "cmdtyName":
                    query = query.addCriteria(Criteria.where("cmdtyName").is(value));
                    break;
                case "cmdtyNameLike":
                    Pattern pattern = Pattern.compile("^.*"+value+".*$", Pattern.CASE_INSENSITIVE);
                    query = query.addCriteria(Criteria.where("cmdtyName").regex(pattern));
                    break;
                case "cmdtyCode":
                    query = query.addCriteria(Criteria.where("cmdtyCode").is(value));
                    break;
                default:
                    break;
            }
        }
        return query;
    }

    protected Update getUpdater(Map<String, Object> updater) {
        Update update = new Update();
        for(Map.Entry<String, Object> entry : updater.entrySet()){
            update.set(entry.getKey(), entry.getValue());
        }
        return update;
    }

}

 

  b.創建Service

@Service
public class TestService {

    @Resource
    private TestDao dao;

    @Transactional
    public boolean saveCmdty(Cmdty cmdty, Info info){
        dao.saveInfo(info);
//        int a = 1/0;    //回滾測試代碼
        dao.save(cmdty);
        return true;
    }

}

 

  c.測試代碼

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        TestService service = (TestService) applicationContext.getBean("testService");

        //商品信息
        Info info = new Info();
        info.setColor("silver");
        info.setStyle("111");
        //商品
        Cmdty cmdty = new Cmdty();
        cmdty.setCmdtyCode("Ag111");
        cmdty.setCmdtyName("銀111");
        //商品屬性
        List<Attr> attributes = new ArrayList<>();
        Attr attribute = new Attr();
        attribute.setKey("品質");
        attribute.setValue("特優");
        attributes.add(attribute);

        cmdty.setInfo(info);
        cmdty.setAttributes(attributes);

        service.saveCmdty(cmdty, info);


    }

 

 

  d.其他

    ①.排序:

        Sort.Direction direction = isAsc ? Sort.Direction.ASC : Sort.Direction.DESC;
        query.with(new Sort(direction, sort));

    ②.分頁:

        int skip = (pageIndex - 1) * pageSize;
        query.skip(skip).limit(pageSize);

      或者

        Pageable pageable = new PageRequest(pageIndex, pageSize);
        query.with(pageable);

    ③.返回指定字段:

        Document document = new Document();
        for(String field : fields){
            document.put(field, isReturn);
        }
        Query query = new BasicQuery(new Document(), document);

 

 

6.使用 MongoRepository 的方式

  a.書寫Dao接口,繼承 MongoRepository

@Repository
public interface TestRepositoryDao extends MongoRepository<Cmdty, String> {

    @Query(value="{'info.$id': ?0 }")
    public Cmdty findByInfoId(ObjectId id);

    public Cmdty findByCmdtyCode(String cmdtyCode);

}

    注:這種方式也支持 JPA 命名規則

 

  b.書寫Service

@Service
public class TestRepositoryService {

    @Resource
    private TestRepositoryDao dao;

    public Cmdty findByInfoId(String infoId){
        return dao.findByInfoId(new ObjectId(infoId));
    }

    public Cmdty findByCmdtyCode(String cmdtyCode){
        return dao.findByCmdtyCode(cmdtyCode);
    }
}

 

  e.測試

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        TestRepositoryService service = (TestRepositoryService) applicationContext.getBean("testRepositoryService");

//        Cmdty cmdty = service.findByInfoId("5cc15f32a0e5eaeb0413dfde");
        Cmdty cmdty = service.findByCmdtyCode("Ag111");
        System.out.println(cmdty);
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM