springdata简介:
Spring Data采用类对象的方式将O/R映射的支持延伸到了NoSQL数据库。但在各种NoSQL数据库中, 数据结构差异较大, 所以很难形成一种通用的API。 每一种数据存储都有各自一套注释用以标注映射所需要的元信息。
JPA | MongoDB | Neo4j |
---|---|---|
@Entity @Table(name="TUSR") public class User { @Id private String id; @Column(name="fn") private String name; private Date lastLogin; ... } |
@Document(collection="usr") public class User { @Id private String id; @Field("fn") private String name; private Date lastLogin; .. } |
@NodeEntity public class User { @GraphId Long id; private String name; private Date lastLogin; ... } |
如果你已经熟悉JPA实体,不难看出这里用了标准的JPA注释。Spring Data复用了这些标准的注释, 而且没有引入其他新的内容。对象的映射正是由这些JPA的实现完成的。 MangoDB和Neo4j各种需要一套类似的注释。在上面的例子中, 我们使用了类级别的注释collection和nodetype. MangoDB中, collection就相当于关系型数据库的表, 而node和edge则是图形数据库(如Neo4j)的主要数据类型。
每个JPA实体都需要有唯一标识符,即便是MongoDB的文档和Neo4j的节点也是如此。
MongoDB使用@Id这个注释作为唯一标识符(这@Id是在org.springframework.data.annotation包中, 和JPA的@Id并不相同)。Neo4j则使用了@GraphId这个注释。这些属性的值是在域对象成功存储后被设置的。 当类属性的名称和MongoDB的文档中的属性名称不同时, 可以使用@Field注释标注。
同样这两种映射也支持对其他对象的引用,请看下面的例子:
JPA | MongoDB | Neo4j |
---|---|---|
@OneToMany private List<Role> roles; |
private List<Role> roles; | @RelatedTo( type = "has", direction = Direction.OUTGOING) private List<Role> roles; |
在JPA中, 我们使用@OneToMany来标识一对多的关系, 通常多的一端的数据存放在子表中, 通过联合查询获得。MongoDB并不支持文档间的联合查询,默认情况下, 被引用的对象和主对象存储在同一个文档中。当然, 我们也可以通过客户端的虚拟联合查询引用其他文档的数据。在Neo4j中, 关系被称作edges, 而edge也是一个基本的数据类型。
总结来说, MongoDB和Neo4j所使用的对象映射和我们大家所熟悉的JPA O/R映射非常类似, 但由于不同的数据结构,两者存在着显著的区别。但不管怎么说, 基本概念都是实现对象和数据结构的映射。
springdata不可能存在支持所有持久存储的通用API,Spring Data 项目旨在为大家提供一种通用的编码模式。所以个人认为如果是
一个项目中需要操作多种数据库类型可以尝试使用如果都是使用统一数据库则最好不要使用
springdata关于jpa的例子:http://nhy520.iteye.com/blog/1158716(一般springdata关于简化jpa用的较多毕竟jpa发展最早)
1.下载对应的jar包
2.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" xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr" 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 http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd http://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd"> <context:annotation-config /> <context:component-scan base-package="org.*"> <context:exclude-filter type="annotation" expression="org.springframework.context.annotation.Configuration" /> </context:component-scan> <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> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg ref="mongo" /> <constructor-arg name="databaseName" value="test" /><!-- 链接数据库的名字 --> </bean> <bean id="natureRepository" class="org.senssic.repository.impl.NatureRepositoryImpl"> </bean> </beans>
3.编写实体类并注解
package org.senssic.bean; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document public class Person { @Id private String id; private String name; private int age; private Address address; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } }
package org.senssic.bean; public class Address { private String addr; private String pro; public String getAddr() { return addr; } public void setAddr(String addr) { this.addr = addr; } public String getPro() { return pro; } public void setPro(String pro) { this.pro = pro; } }
3.编写操作接口
package org.senssic.repository; import java.util.List; import com.mongodb.WriteResult; public interface Repository<T> { public List<T> getAllObjects(); public void saveObject(T object); public T getObject(String id); public WriteResult updateObject(String id, String name); public void deleteObject(String id); public void createCollection(); public void dropCollection(); }
4.编写接口实现
package org.senssic.repository.impl; import java.util.List; import javax.annotation.Resource; import org.senssic.bean.Person; import org.senssic.repository.Repository; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import com.mongodb.WriteResult; public class NatureRepositoryImpl implements Repository<Person> { @Resource MongoTemplate mongoTemplate; @Override public List<Person> getAllObjects() { return mongoTemplate.findAll(Person.class); } @Override public void saveObject(Person tree) { mongoTemplate.insert(tree); } @Override public Person getObject(String id) { return mongoTemplate.findOne(new Query(Criteria.where("id").is(id)), Person.class); } @Override public WriteResult updateObject(String id, String name) { return mongoTemplate.updateFirst( new Query(Criteria.where("id").is(id)), Update.update("name", name), Person.class); } @Override public void deleteObject(String id) { mongoTemplate.remove(new Query(Criteria.where("id").is(id)), Person.class); } @Override public void createCollection() { if (!mongoTemplate.collectionExists(Person.class)) { mongoTemplate.createCollection(Person.class); } } @Override public void dropCollection() { if (mongoTemplate.collectionExists(Person.class)) { mongoTemplate.dropCollection(Person.class); } } }
5.测试类
package org.senssic.test; import org.senssic.bean.Address; import org.senssic.bean.Person; import org.senssic.repository.Repository; import org.senssic.repository.impl.NatureRepositoryImpl; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MongoTest { public static void main(String[] args) { ConfigurableApplicationContext context = new ClassPathXmlApplicationContext( "classpath:/spring-config.xml"); Repository<Person> repository = context .getBean(NatureRepositoryImpl.class); repository.dropCollection(); repository.createCollection(); Person person = new Person(); Address address = new Address(); address.setAddr("合肥"); address.setPro("安徽"); person.setAddress(address); person.setAge(20); person.setName("senssic"); person.setId("1"); repository.saveObject(person); System.out.println("1. " + repository.getAllObjects()); person.setId("101"); repository.saveObject(person); System.out.println("2. " + repository.getAllObjects()); System.out.println("Tree with id 1" + repository.getObject("1")); repository.updateObject("1", "sen"); System.out.println("3. " + repository.getAllObjects()); repository.deleteObject("1"); System.out.println("4. " + repository.getAllObjects()); context.close(); } }