Spring Data for Mongo 介绍
2015-06-14 23:42
459 查看
本文将快速介绍 Spring Data for Mongo 的使用。
Spring Data for MongoDB是Spring Data的一个子模块。 目标是为MongoDB提供一个相近的一致的基于Spring的编程模型。
Spring Data for MongoDB核心功能是映射POJO到Mongo的DBCollection中的文档,并且提供Repository 风格数据访问层。
相似的ORM/持久化框架还有
morphia : MongoDB官方支持的ORM框架,可以很好的和Spring, Guice等DI框架集成,使用起来很方便。
Hibernate OGM : Hibernate提供了Hibernate风格的NoSql ORM框架。
jongo : 提供Mongo shell一样灵活的查询,并且提供ORM by Jackson,和Mongo java driver一样快。
可以通过@Configuration注解或者XML风格配置
MongoTemplate 辅助类 (类似JdbcTemplate),方便常用的CRUD操作
异常转换
丰富的对象映射
通过注解指定对象映射
持久化和映射声明周期事件
通过MongoReader/MongoWriter 定义底层的映射
基于Java的Query, Criteria, Update DSL
自动实现Repository,可以提供定制的查找
QueryDSL 支持类型安全的查询
跨数据库平台的持久化 - 支持JPA with Mongo
GeoSpatial 支持
Map-Reduce 支持
JMX管理和监控
CDI 支持
GridFS 支持
本文介绍的Spring Data for MongoDB版本为1.7.0.M1。
Spring Data for MongoDB提供了两种编程风格来应用MongoDB,下面逐一介绍这两种方式。
Spring Data提供了repository 抽象方式,可以极大的减少数据访问层千篇一律的类似的重复的代码。 基本DAO都会实现,find,findAll, findById, save, delete,update等方法,而且代码逻辑基本一致。Spring Data提供了简化方法,通过接口定义 Spring Data通过Proxy自动提供具体的实现。
这里有一篇介绍 文章 。
Spring Data最重要的接口是
同时也提供特定数据库的接口:
这些接口继承
可以增加一些特定的统计和删除方法。
标准的CRUD功能的repositories一般会提供一些查询方法。在Spring Data中只需四步。
1) 声明一个子接口:
2) 声明查询方法
3) 设置Spring为这些接口产生Proxy实例:两种方式。
或
4) 注入此repository实例并使用它
第一步就是为特定的domain类定义相应的定义repository。
调整repository 定义
典型的,repository 接口应该继承
如果你不想继承这些接口,使用
repository proxy有两种方式根据方法导出数据库特定的语句。 一种是根据方法名直接导出。 另一种是是手工定义。
Query lookup策略
通过XML方式的query-lookup-strategy 属性或者${store}注解的queryLookupStrategy 指定。
CREATE: 根据方法名
USE_DECLARED_QUERY: 通过注解或者其它方式得到
CREATE_IF_NOT_FOUND: 复合前面两种
Query creation
方法名应该是find…By, read…By, query…By, count…By, and get…By这样的格式。可以设置Distinct 和
Property expressions
假定
更明确的用:
特殊参数
限制查询结果
XML配置方式
使用筛选器:
JavaConfig方式
使用@Enable${store}Repositories注解。如
编程方式
如果觉得默认的约定不够,可以定制实现。
注意实现名是接口名加
你可以到 这里 下载例子。
相关文件:
以上啰嗦了很多,感觉和Mongo关系不大。 这是Spring Data为各种数据库如JPA,Mongo提供的一种统一的方式。 理论上来说,无论你使用Mysql, Oracle,Mongo,都可以采用这种方式组织你的代码。
但是, Spring Data for MongoDB还提供了另外一种方式, 类似JdbcTemplate的方式。 这种方式你可以自己定义你的repository的编程方式。 这种方式让你感觉更灵活, 不被上面的各种约定束缚住。
你可以通过XML或者JavaConfig方式配置MongoTemplate.
1) JavaConfig方式
或者
2) XML方式
可以设置更多的参数。
如果你想将MongoTemplate配置成Spring Bean:
或者XML:
此接口定义了众多的操作方法如”find”, “findAndModify”, “findOne”, “insert”, “remove”, “save”, “update” and “updateMulti”等。
它转换domain object为
缺省转换类为
它有几个构造函数:
MongoTemplate(Mongo mongo, String databaseName)
MongoTemplate(Mongo mongo, String databaseName, UserCredentials userCredentials)
MongoTemplate(MongoDbFactory mongoDbFactory)
MongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter)
在这种方式下,你需要自己实现Repository的具体类。
一般情况下你需要为所有的Repository实现一个抽象的父类,在父类中实现大部分CRUD操作。 在子类中实现特定的操作方法。
你的Repository可以实现MongoRepository或者CrudRepository接口,但是不是必须的。
本例子中简单实现了一个简单的Repository,纯演示使用。
在这种情况下,方法名比较自由,你毋须遵守某种约定。
http://docs.spring.io/spring-data/data-mongo/docs/1.7.0.M1/reference/html/
Spring Data for MongoDB是Spring Data的一个子模块。 目标是为MongoDB提供一个相近的一致的基于Spring的编程模型。
Spring Data for MongoDB核心功能是映射POJO到Mongo的DBCollection中的文档,并且提供Repository 风格数据访问层。
相似的ORM/持久化框架还有
morphia : MongoDB官方支持的ORM框架,可以很好的和Spring, Guice等DI框架集成,使用起来很方便。
Hibernate OGM : Hibernate提供了Hibernate风格的NoSql ORM框架。
jongo : 提供Mongo shell一样灵活的查询,并且提供ORM by Jackson,和Mongo java driver一样快。
特性:
可以通过@Configuration注解或者XML风格配置MongoTemplate 辅助类 (类似JdbcTemplate),方便常用的CRUD操作
异常转换
丰富的对象映射
通过注解指定对象映射
持久化和映射声明周期事件
通过MongoReader/MongoWriter 定义底层的映射
基于Java的Query, Criteria, Update DSL
自动实现Repository,可以提供定制的查找
QueryDSL 支持类型安全的查询
跨数据库平台的持久化 - 支持JPA with Mongo
GeoSpatial 支持
Map-Reduce 支持
JMX管理和监控
CDI 支持
GridFS 支持
本文介绍的Spring Data for MongoDB版本为1.7.0.M1。
Spring Data for MongoDB提供了两种编程风格来应用MongoDB,下面逐一介绍这两种方式。
Spring Data Repository 风格
Spring Data提供了repository 抽象方式,可以极大的减少数据访问层千篇一律的类似的重复的代码。 基本DAO都会实现,find,findAll, findById, save, delete,update等方法,而且代码逻辑基本一致。Spring Data提供了简化方法,通过接口定义 Spring Data通过Proxy自动提供具体的实现。这里有一篇介绍 文章 。
核心概念
Spring Data最重要的接口是 Repository。它使用域类型和它的ID类型作为类型参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public interface CrudRepository < T , ID extends Serializable > extends Repository < T , ID > { <S extends T> S save (S entity) ; T findOne (ID primaryKey) ; Iterable<T> findAll () ; Long count () ; void delete (T entity) ; boolean exists (ID primaryKey) ; // … more functionality omitted. } |
JpaRepository和
MongoRepository。
这些接口继承
CrudRepository。
CrudRepository之上还有一个接口
PagingAndSortingRepository提供分页的功能。
1 2 3 4 5 6 7 | public interface PagingAndSortingRepository < T , ID extends Serializable > extends CrudRepository < T , ID > { Iterable<T> findAll (Sort sort) ; Page<T> findAll (Pageable pageable) ; } |
1 2 3 | public interface UserRepository extends CrudRepository < User , Long > { Long countByLastname (String lastname) ; } |
1 2 3 4 | public interface UserRepository extends CrudRepository < User , Long > { Long deleteByLastname (String lastname) ; List<User> removeByLastname (String lastname) ; } |
查询方法
标准的CRUD功能的repositories一般会提供一些查询方法。在Spring Data中只需四步。1) 声明一个子接口:
interface PersonRepository extends Repository<User, Long> { … }
2) 声明查询方法
1 2 3 | interface PersonRepository extends Repository < User , Long > { List<Person> findByLastname (String lastname) ; } |
1 2 3 4 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @EnableJpaRepositories class Config {} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?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:jpa = "http://www.springframework.org/schema/data/jpa" xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> < jpa:repositories base-package = "com.acme.repositories" /> </ beans > |
1 2 3 4 5 6 7 8 9 | public class SomeClient { @Autowired private PersonRepository repository; public void doSomething () { List<Person> persons = repository.findByLastname( "Matthews" ); } } |
定义repository 接口
第一步就是为特定的domain类定义相应的定义repository。调整repository 定义
典型的,repository 接口应该继承
Repository,
CrudRepository,
PagingAndSortingRepository。
如果你不想继承这些接口,使用
@RepositoryDefinition注解标记此接口为repository。
@NoRepositoryBean增加一些非典型的方法,然后在domain class Repository继承它。
1 2 3 4 5 6 7 8 9 10 11 | @NoRepositoryBean interface MyBaseRepository < T , ID extends Serializable > extends Repository< T , ID > { T findOne (ID id) ; T save (T entity) ; } interface UserRepository extends MyBaseRepository < User , Long > { User findByEmailAddress (EmailAddress emailAddress) ; } |
定义查询方法
repository proxy有两种方式根据方法导出数据库特定的语句。 一种是根据方法名直接导出。 另一种是是手工定义。Query lookup策略
通过XML方式的query-lookup-strategy 属性或者${store}注解的queryLookupStrategy 指定。
CREATE: 根据方法名
USE_DECLARED_QUERY: 通过注解或者其它方式得到
CREATE_IF_NOT_FOUND: 复合前面两种
Query creation
方法名应该是find…By, read…By, query…By, count…By, and get…By这样的格式。可以设置Distinct 和
And,
Or:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public interface PersonRepository extends Repository < User , Long > { List<Person> findByEmailAddressAndLastname (EmailAddress emailAddress, String lastname) ; // Enables the distinct flag for the query List<Person> findDistinctPeopleByLastnameOrFirstname (String lastname, String firstname) ; List<Person> findPeopleDistinctByLastnameOrFirstname (String lastname, String firstname) ; // Enabling ignoring case for an individual property List<Person> findByLastnameIgnoreCase (String lastname) ; // Enabling ignoring case for all suitable properties List<Person> findByLastnameAndFirstnameAllIgnoreCase (String lastname, String firstname) ; // Enabling static ORDER BY for a query List<Person> findByLastnameOrderByFirstnameAsc (String lastname) ; List<Person> findByLastnameOrderByFirstnameDesc (String lastname) ; } |
假定
Person有
Address,
Address有
ZipCode属性。
List<Person> findByAddressZipCode(ZipCode zipCode);会使用x.address.zipCode遍历。
更明确的用:
1 | List<Person> findByAddress_ZipCode (ZipCode zipCode) ; |
1 2 3 4 | Page<User> findByLastname (String lastname, Pageable pageable) ; Slice<User> findByLastname (String lastname, Pageable pageable) ; List<User> findByLastname (String lastname, Sort sort) ; List<User> findByLastname (String lastname, Pageable pageable) ; |
1 2 3 4 5 6 | User findFirstByOrderByLastname () ; User findTopByOrderByAgeDesc () ; Page<User> queryFirst10ByLastname (String lastname, Pageable pageable) ; Slice<User> findTop3ByLastname (String lastname, Pageable pageable) ; List<User> findFirst10ByLastname (String lastname, Sort sort) ; List<User> findTop10ByLastname (String lastname, Pageable pageable) ; |
产生repository实例
XML配置方式1 2 3 4 5 6 7 8 9 10 11 | <?xml version="1.0" encoding="UTF-8"?> < beans:beans xmlns:beans = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns = "http://www.springframework.org/schema/data/jpa" xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> < repositories base-package = "com.acme.repositories" /> </ beans:beans > |
1 2 3 | < repositories base-package = "com.acme.repositories" > < context:exclude-filter type = "regex" expression = ".*SomeRepository" /> </ repositories > |
使用@Enable${store}Repositories注解。如
EnableMongoRepositories,
EnableJpaRepositories
1 2 3 4 5 6 7 8 9 | @Configuration @EnableJpaRepositories ( "com.acme.repositories" ) class ApplicationConfiguration { @Bean public EntityManagerFactory entityManagerFactory () { // … } } |
1 2 | RepositoryFactorySupport factory = … // Instantiate factory here UserRepository repository = factory.getRepository(UserRepository.class); |
定制Repository实现
如果觉得默认的约定不够,可以定制实现。1 2 3 4 5 6 7 8 9 10 | interface UserRepositoryCustom { public void someCustomMethod (User user) ; } class UserRepositoryImpl implements UserRepositoryCustom { public void someCustomMethod (User user) { // Your custom implementation } } |
Impl。 不过可以定制后缀。
1 2 | < repositories base-package = "com.acme.repository" /> < repositories base-package = "com.acme.repository" repository-impl-postfix = "FooBar" /> |
相关文件:
文件 | 描述 |
---|---|
config/MongoConfig | Spring配置文件,替代Spring XML配置文件 |
entity/Customer | domain object |
entity/Address | domain object |
repository/CustomerRepository | DAO层接口 |
APP | 测试类 |
MongoTemplate方式
以上啰嗦了很多,感觉和Mongo关系不大。 这是Spring Data为各种数据库如JPA,Mongo提供的一种统一的方式。 理论上来说,无论你使用Mysql, Oracle,Mongo,都可以采用这种方式组织你的代码。但是, Spring Data for MongoDB还提供了另外一种方式, 类似JdbcTemplate的方式。 这种方式你可以自己定义你的repository的编程方式。 这种方式让你感觉更灵活, 不被上面的各种约定束缚住。
你可以通过XML或者JavaConfig方式配置MongoTemplate.
1) JavaConfig方式
1 2 3 4 5 6 | /* * Use the standard Mongo driver API to create a com.mongodb.Mongo instance. */ public @Bean Mongo mongo () throws UnknownHostException { return new Mongo( "localhost" ); } |
1 2 3 4 5 6 7 8 | /* * Factory bean that creates the com.mongodb.Mongo instance */ public @Bean MongoFactoryBean mongo( ) { MongoFactoryBean mongo = new MongoFactoryBean( ) ; mongo.setHost( "localhost" ) ; return mongo; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?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 / 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-1.0.xsd * http: // www.springframework.org / schema / beans http: // www.springframework.org / schema / beans / spring-beans-3.0.xsd "> <!-- Default bean name is 'mongo' --> * < mongo:mongo host = "localhost" port = "27017" /> * </ beans > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | < beans > < mongo:mongo host = "localhost" port = "27017" > < mongo:options connections-per-host = "8" threads-allowed-to-block-for-connection-multiplier = "4" connect-timeout = "1000" max-wait-time = "1500}" auto-connect-retry = "true" socket-keep-alive = "true" socket-timeout = "1500" slave-ok = "true" write-number = "1" write-timeout = "0" write-fsync = "true" /> </ mongo:mongo /> </ beans > |
1 2 3 4 5 6 7 8 9 10 11 12 | @Configuration public class MongoConfiguration { public @Bean MongoDbFactory mongoDbFactory () throws Exception { UserCredentials userCredentials = new UserCredentials( "joe" , "secret" ); return new SimpleMongoDbFactory( new Mongo(), "database" , userCredentials); } public @Bean MongoTemplate mongoTemplate () throws Exception { return new MongoTemplate(mongoDbFactory()); } } |
1 2 3 4 5 6 | < mongo:db-factory id = "anotherMongoDbFactory" host = "localhost" port = "27017" dbname = "database" username = "joe" password = "secret" /> |
MongoTemplate
MongoTemplate提供了非常多的操作MongoDB的方法。 它是线程安全的,可以在多线程的情况下使用。
MongoTemplate实现了
MongoOperations接口,
此接口定义了众多的操作方法如”find”, “findAndModify”, “findOne”, “insert”, “remove”, “save”, “update” and “updateMulti”等。
它转换domain object为
DBObject,并提供了Query, Criteria, and Update等流式API。
缺省转换类为
MongoMappingConverter。
它有几个构造函数:
MongoTemplate(Mongo mongo, String databaseName)
MongoTemplate(Mongo mongo, String databaseName, UserCredentials userCredentials)
MongoTemplate(MongoDbFactory mongoDbFactory)
MongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter)
Repository
在这种方式下,你需要自己实现Repository的具体类。一般情况下你需要为所有的Repository实现一个抽象的父类,在父类中实现大部分CRUD操作。 在子类中实现特定的操作方法。
你的Repository可以实现MongoRepository或者CrudRepository接口,但是不是必须的。
本例子中简单实现了一个简单的Repository,纯演示使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Sort; import org.springframework.data.geo.Circle; import org.springframework.data.geo.Distance; import org.springframework.data.geo.GeoResults; import org.springframework.data.geo.Point; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.stereotype.Repository; import com.colobu.springmongo.entity.Customer; @Repository public class AnotherCustomerRepository { @Autowired private MongoTemplate mongoTemplate; public Customer save (Customer c) { mongoTemplate.save(c); return c; } public void deleteAll () { mongoTemplate.dropCollection(Customer.class); } public List<Customer> findAll () { return mongoTemplate.findAll(Customer.class); } public List<Customer> findByLastname (String lastname, Sort sort) { Criteria criteria = new Criteria( "lastname" ).is(lastname); return mongoTemplate.find( new Query(criteria), Customer.class); } public GeoResults<Customer> findByAddressLocationNear (Point point, Distance distance) { return mongoTemplate.geoNear(NearQuery.near(point).maxDistance(distance), Customer.class); } } |
参考文档
http://docs.spring.io/spring-data/data-mongo/docs/1.7.0.M1/reference/html/
相关文章推荐
- Java中的对象和对象引用
- Java: 面向对象程序设计(下)
- SpringMVC 上传文件
- java——jdk1.5新特性
- [狗尾续貂第一篇]--通向架构师的道路(第十九天)使用maven构建Spring工程 [向lifetragedy致敬!!]
- 14-06-2015 Java_Home and Path
- Spring学习——DI(依赖注入)
- JDK,JRE,JVM区别与联系
- java对象克隆之深度克隆 deep clone
- java 框架基础知识(5)----注解-->Spring配置
- java 基础static关键字
- 在Servlet Filter中使用Spring容器
- Java之CyclicBarrier使用
- spring mvc messageConverters及406等问题
- java链表
- java线程和进程(运用多线程的小球碰撞游戏)
- Java 信号量 Semaphore 介绍
- java实现简单的窗体和密码验证(传参,事件机制和事件监听的作用过程)
- java图形界面基础之画图(使用Graphics类从画图形到图片到gif)
- java的数组队列和泛型