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);
}
上一篇:XAMPP 的MYSQL无法启动


下一篇:(译)你应该知道的jQuery技巧