`

spring与mongodb使用教程之整合的三种方式

 
阅读更多

这一章是mongodb的使用基础篇 为以后讲spring hadoop 之 mongodb整合做基础教程

常用了web项目使用mongodb 与 spring整合一般有三种方式 此三种方式我都用过多次,个人比较喜欢第三种 

 

 1.原生驱动直接与spring整合

2.google Morphia开源库

3 spring data mongodb spring data子项目

我会在本文一种一种依次讲解 如果有什么疑问 可以在下面留言 

第一种方式 直接整合 spring

第一步 添加maven相关依赖

 

1
2
3
4
5
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>2.10.1</version>
</dependency>

 

第二步 实现mongodb工程 

在讲这一步之前 我先引入官方的一篇博客教程http://docs.mongodb.org/manual/applications/crud/

DBobject 这个对象,key -value 格式 他是mongodb的文档每一行的Bjson 在java中体现的对象 常用的有BasicDBObject 

下面我们自定义实现个mongodbFactory工厂 这是我写的一个与spring整合的类

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
 
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import com.mongodb.MongoOptions;
import com.mongodb.ServerAddress;
 
/**
 *
 *     
 *    
 * @author zhuyuping      
 * @version 1.0    
 * @created 2013-11-11 下午4:59:31
 * @functions:
 */
public class MongoDBFactoryBean implements FactoryBean<Mongo>,InitializingBean,DisposableBean{
 
        private Mongo mongo;
 
        private String host;
 
        private boolean autoConnectRetry;
 
        private int connectionsPerHost;//每个主机的连接数
 
        private int threadsAllowedToBlockForConnectionMultiplier = 10;//线程队列数,它以上面 connectionsPerHost值相乘的结果就是线程队列最大值。如果连接线程排满了队列就会抛出“Out of semaphores to get db”错误。
 
        private boolean fsync = false;
         
        private int maxWaitTime=120000;//ms 
         
        private int connectTimeout=10000;
     
 
        public void setHost(String host)
        {
            this.host = host;
        }
 
 
        public void setAutoConnectRetry(boolean autoConnectRetry)
        {
            this.autoConnectRetry = autoConnectRetry;
        }
 
     
 
        public void setConnectionsPerHost(int connectionsPerHost)
        {
            this.connectionsPerHost = connectionsPerHost;
        }
 
         
        public void setThreadsAllowedToBlockForConnectionMultiplier(int threadsAllowedToBlockForConnectionMultiplier)
        {
            this.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
        }
 
         
        public void setFsync(boolean fsync)
        {
            this.fsync = fsync;
        }
 
         
        public void setMaxWaitTime(int maxWaitTime)
        {
            this.maxWaitTime = maxWaitTime;
        }
 
         
 
        public void setConnectTimeout(int connectTimeout)
        {
            this.connectTimeout = connectTimeout;
        }
 
    public void destroy() throws Exception
    {
         
        this.mongo.close();
    }
 
    public void afterPropertiesSet() throws Exception
    {
        ServerAddress server = new ServerAddress(host);
 
        MongoOptions options = new MongoOptions();
        options.autoConnectRetry = this.autoConnectRetry;
        options.connectionsPerHost = this.connectionsPerHost;
        options.threadsAllowedToBlockForConnectionMultiplier = this.threadsAllowedToBlockForConnectionMultiplier;
        options.fsync = this.fsync;
        options.connectTimeout=this.connectTimeout;
        options.maxWaitTime=this.maxWaitTime;
 
        this.mongo = new Mongo(server, options);
         
    }
 
    public Mongo getObject() throws Exception
    {
         
        return mongo;
    }
 
    public Class<?> getObjectType()
    {
         
        return Mongo.class;
    }
 
    public boolean isSingleton()
    {
         
          return true;
    }
     
 
    public  DB getDB(String dbname) throws Exception {
         
        return getObject().getDB(dbname);
    }
     
     
    public  DBCollection getCollection(String dbname, String collection) throws Exception {
         
        return getDB(dbname).getCollection(collection);
    }
     
    

 

下面在spring配置文件中配置

1
2
<bean id="mongo" class="com.zyp.mongodb.MongoDBFactoryBean" p:host="localhost" p:autoConnectRetry=true p:connectionsPerHost=10 p:fsync=true>
</bean>

下面在dao层 或者service层 中使用

1
2
3
4
5
6
7
8
9
10
@Service("userService")
@Transactional
public class UserService implements IUserService   {
     
    protected static Logger logger = Logger.getLogger("service");
     
    @Autowired
    protected Mongo mongo;
     
    

下面写一个findAll方法 其他的一样 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public List<DBobject> getAll() {
  
   
  
    DBCollection coll = mongo.getCollection("zhuyuping","test");
     
    DBCursor cur = coll.find();
     
 List<DBObject> items = new ArrayList<dbobject>();
  
       while(cur.hasNext()) {
       
        items.add(cur.next());
       }
         
        
 return items;
}

这里DbObject对象 可以通过反射转换成相应的类 ,这里甚至可以自己写注解 ,因为DbObject你可以看成是Map对象 你还可以自定义一个MongoTemplate 这样就是spring data mongodb 精简版

第二节morphia 使用教程以及与spring整合

第一步添加morphia的相关依赖 

1
2
3
<groupId>org.mongodb.morphia</groupId>
<artifactId>morphia</artifactId>
<version>###</version>

在讲整合之前先介绍下morphia morphia 

首先morphia的架构跟hibernate Jpa 差不多,他的dataStore类似 session有增删改查 加索引 mapReduce 特别是同hibernate一样的createQuery 还有hibernate ODB方式 ,不过这种方式他内嵌到query中,这里不得不说 就是morphia使用createQuery 查询时候 同hibernate 也是返回一个Query对象,更重要的是都是链式编程 而query具有动态拼接 特别是排序 limit 分页 等等特性 下面贴出2张详细介绍图



还要说下morphia这个类 他类似sessionfactory 在后面我们自定义实现一个morphia整合要用到他

下面讲一下 他类似hibernate 的注解方面 以及 JPA实体监听器 hibernate拦截器方面

@Entity @Id @Indexed @Transisit @Property 

上面几个基本注解顾名思义 ,这里要提的是mongodb数据库设计 有2中 一种是内嵌 还有一个是外链

这个在百度有好多相关资料,前一种是默认 也就是说 如果你user 有好多角色 在用户实体中有List<Role> roles=Lists.newArrayList(); 我们知道hibernate 字段不写注解默认是@Base 也会映射 如果你不需要加上@Transisit 内嵌方式 就是user这个document 存user 对象也会把role存入 怎么说呢 一个先天的级联查询

这是网上一张图 就是一个用户信息表 里面内嵌了一个addres 显然这是1对1 同样可以1对多 ,多对多可以转换成1对多 中间表 这样所有的关联都可以对应了,这里要值得一提的是 ,吐过address少量信息的话 采用这种方式效率很高,如果有成百上千个address那会造成一个document的每一个对象过大 

这里就有第二种方式叫做外链 ,其实类似于关系数据库中的外键,也就是说 1对多 可以在多的一方建立外键

同理 下面看看 

对于内嵌方式 注解是@Embedded 只要在list set ....属性上加上改注解即可 ,,因为默认方式是内嵌 所以我一般都不写注解就可以了,

对于外链方式 注解是@Reference 在属性上加上该最 表示与该属性的类建立外键关联方式 这些注解都可以配置自定义字段名字 ,注意导包不要导错了。是morphia 的 不是jpa 规范的 也不是hibernate 也不是spring data 的 

还有我们知道在hibernate 或者说是 JPA 规范中还有实体监听器 乐观锁 

同样morphia 既然是类似它 他同样也有 

应用官方的一段文字

Lifecycle Method Annotations
There are various annotations which can be used to register callbacks on certain lifecycle events. These include Pre/Post-Persist (Save), and Pre/Post-Load.


@PrePersist - Called before save, it can return a DBObject in place of an empty one.
@PostPersist - Called after the save call to the datastore
@PreLoad - Called before mapping the datastore object to the entity (POJO); the DBObject is passed as an argument (you can add/remove/change values)
@PostLoad - Called after mapping to the entity
See the AllAnnotation for a full list of the annotations supported.
 这几个注解跟JPA 一样的意思,他们都是注释在方法上

 

1
2
3
4
5
6
class BankAccount {
  @Id String id;
  Date lastUpdated = new Date();
 
  @PrePersist void prePersist() {lastUpdated = new Date();}
}

同样乐观锁 @version注解 也是意思相同

讲到这里 我们大体的介绍介绍完了 

我们来看我们怎么整合 spring 

下面是我写的一个类 这里我不采用上面的那种方式了 我换一种实现,上面那种配置参数多了 我都不想写了 

我配置多个类 这种方式唯一的坏处就是 他对mongo 那方面配置如数据库名称 解耦不了 ,不过我们可以代理mongo 或者继承实现一个自定义的mongo 就可以了

 

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/**
 *
 *     
 *    
 * @author zhuyuping      
 * @version 1.0    
 * @created 2013-11-12 下午12:47:54
 * @functions:
 */
public class MorphiaFactoryBean extends Morphia implements InitializingBean
{
 
    private Mongo mongo = null;
 
    private String dbName = null;
 
    private Datastore ds = null;
 
    private DB db = null;
     
    private String packgeScanName=null;
 
    public Datastore getDataStore()
    {
        if ( this.mongo == null || this.dbName == null ) { return null; }
        if ( ds == null )
        {
            ds = createDatastore( mongo , dbName );
            db = ds.getDB();
        }
        return ds;
    }
 
     
     
 
 
 
    public void setPackgeScanName(String packgeScanName)
    {
        this.packgeScanName = packgeScanName;
    }
 
 
 
    public Mongo getMongo()
    {
        return mongo;
    }
 
    public void setMongo( Mongo mongo )
    {
        this.mongo = mongo;
    }
 
 
 
    public void setDbName( String dbName )
    {
        this.dbName = dbName;
    }
 
    public void afterPropertiesSet() throws Exception
    {
        if ( this.mongo == null || this.dbName == null || this.packgeScanName==null) { return; }
        if ( ds == null )
        {
            ds = createDatastore( mongo , dbName );
            db = ds.getDB();
        }
        //应该抛出详细的异常信息 告诉要配置mongo 必须配置mongod 以及dbName packegeScanName
        mapPackage(packgeScanName);
    }
 
    public DB getDb()
    {
        return db;
    }
 
     
 
}

ok 下面就整合他吧

 

1
2
3
4
5
6
7
8
9
10
11
<!-- Mongodb数据库 -->
    <bean id="mongo" class="com.mongodb.Mongo">
        <constructor-arg type="String" value="localhost"></constructor-arg>
        <constructor-arg type="int" value="11217"></constructor-arg>
    </bean>
     
    <bean id="morphia" class="com.zyp.mongo.MorphiaFactoryBean">
        <property name="dbName" value="${mongoDName}"></property>
        <property name="mongo" ref="mongo"></property>
               <property name="packgeScanName" >com.zyp.mongodb.model</property>
    </bean>
1
2
@Resource( name = "morphia" )
protected MorphiaFactoryBean morphia;

注入了上述在泛型baseDaoImpl 之后 就可以 使用了 看

morphia.getDataStore().xxx 增删改查 。。。等等 上面已经讲了DataStore的强大 这里注意你可以完全像hibernate那样操作他,因为实体被我们映射了 ,当然你也可以用原始的方式

 

第三种方式 spring data mongodb 

说道spring data mongodb ,他是spring data的 一个子项目,统一和简化对各类型持久化存储, 而不拘泥于是关系型数据库还是NoSQL 数据存储。常用的有spring data JPA JDBC mongodb neo4j 这里我会都有提及 ,Spring Data提供了基于这些层面的统一接口(CrudRepository,PagingAndSortingRepository)以及对持久化存储的实现。 所有的spring data 都提供了模板 orm映射实现 对象访问持久化 分页 通用支持 在我的博客中提及到了spring data jdbc querydsl的用法 这里我讲一下JPA mongodb neo4j的用法 

第一步 加入相应的依赖

spring data 这里我一次性整合所有的 所以依赖全部加进去

 

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
       <dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-jdbc-core</artifactId>
  <version>${springdata.version}</version>
</dependency>
 
 
<dependency>
 <groupId>org.springframework.data</groupId>
 <artifactId>spring-data-commons</artifactId>
 <version>1.5.2.RELEASE</version>
</dependency>
 
             
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-mongodb</artifactId>
            <version>${sd.mongodb.version}</version>
        </dependency>
 
 
        <!-- Neo4J -->
 
    <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-neo4j</artifactId>
    <version>2.2.2.RELEASE</version>
</dependency>

第二部分,加入相关命名空间 使其能够扫描到相应的resposity工厂 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
<?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"
    xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
        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
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
        http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd">

要激活相应的工厂支持 使其能够扫描到相应的 Repository ,这里要提的是因为spring data Repository 相当于一个抽象统一的dao 这个dao将由spring data 去维护映射与持久层的关系,大多数时候是这样的

 

下面是一个spring data jpa的项目

 

1
2
3
4
5
6
7
8
9
10
11
/**
 * 用户DAO接口
 * @author zhuyuping
 * @version 2013-08-01
 */
 
public interface UserDao extends CrudRepository<User, Long>{
 
     
     
}  

看到吧是一个接口 

1
CrudRepository 增删改查 ,如果要支持分页 继承<span style="font-family:Arial, sans-serif;font-size:14px;line-height:21px;background-color:#FFFFFF;">PagingAndSortingRepository 这2个接口是spring data 所有子项目通用的 </span>

但是有时候要是你想支持mongodb一些特性 mapredurce 支持neo4j特性 那么你就需要继承相应的

 

例如neo4j

 

1
2
3
public interface UserRepository extends GraphRepository<User>  {
    User findByUsername(String username);
}

但是此时就不能更数据库解耦了 所以有时候你要自己什么都不需要暴露 也就是说不要他提供的增删改查,很多情况只要查询 你只要继承Repository 即可 

 

同理mongodb的  看到mongodb的吧  不过我不建议你这样用我觉得常用的 继承crud即可 或者pagexx即可 这样 你以后可以随意的更换各种数据库,关于这里 统一数据库的 我博客有几篇讲到querydsl的 他也可以,你们也可以去看看 支持SQL NOSQL的建立在hibernate mybatis之上的统一api层 


这里还要说一下我们怎么写方法的问题,这里官方手册很详细,只是需要提的是

查找方式以及自定义查询接口 注解方式  还有自己自定义实现

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
通过解析方法名创建查询
通过前面的例子,读者基本上对解析方法名创建查询的方式有了一个大致的了解,这也是 Spring Data JPA 吸引开发者的一个很重要的因素。该功能其实并非 Spring Data JPA 首创,而是源自一个开源的 JPA 框架 Hades,该框架的作者 Oliver Gierke 本身又是 Spring Data JPA 项目的 Leader,所以把 Hades 的优势引入到 Spring Data JPA 也就是顺理成章的了。
框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如 find、findBy、read、readBy、get、getBy,然后对剩下部分进行解析。并且如果方法的最后一个参数是 Sort 或者 Pageable 类型,也会提取相关的信息,以便按规则进行排序或者分页查询。
在创建查询时,我们通过在方法名中使用属性名称来表达,比如 findByUserAddressZip ()。框架在解析该方法时,首先剔除 findBy,然后对剩下的属性进行解析,详细规则如下(此处假设该方法针对的域对象为 AccountInfo 类型):
先判断 userAddressZip (根据 POJO 规范,首字母变为小写,下同)是否为 AccountInfo 的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;
从右往左截取第一个大写字母开头的字符串(此处为 Zip),然后检查剩下的字符串是否为 AccountInfo 的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设 user 为 AccountInfo 的一个属性;
接着处理剩下部分( AddressZip ),先判断 user 所对应的类型是否有 addressZip 属性,如果有,则表示该方法最终是根据 "AccountInfo.user.addressZip" 的取值进行查询;否则继续按照步骤 2 的规则从右往左截取,最终表示根据 "AccountInfo.user.address.zip" 的值进行查询。
可能会存在一种特殊情况,比如 AccountInfo 包含一个 user 的属性,也有一个 userAddress 属性,此时会存在混淆。读者可以明确在属性之间加上 "_" 以显式表达意图,比如 "findByUser_AddressZip()" 或者 "findByUserAddress_Zip()"
在查询时,通常需要同时根据多个属性进行查询,且查询的条件也格式各样(大于某个值、在某个范围等等),Spring Data JPA 为此提供了一些表达条件查询的关键字,大致如下:
And --- 等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd);
Or --- 等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr);
Between --- 等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min);
LessThan --- 等价于 SQL 中的 "<",比如 findBySalaryLessThan(int max);
GreaterThan --- 等价于 SQL 中的">",比如 findBySalaryGreaterThan(int min);
IsNull --- 等价于 SQL 中的 "is null",比如 findByUsernameIsNull();
IsNotNull --- 等价于 SQL 中的 "is not null",比如 findByUsernameIsNotNull();
NotNull --- 与 IsNotNull 等价;
Like --- 等价于 SQL 中的 "like",比如 findByUsernameLike(String user);
NotLike --- 等价于 SQL 中的 "not like",比如 findByUsernameNotLike(String user);
OrderBy --- 等价于 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user);
Not --- 等价于 SQL 中的 "! =",比如 findByUsernameNot(String user);
In --- 等价于 SQL 中的 "in",比如 findByUsernameIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
NotIn --- 等价于 SQL 中的 "not in",比如 findByUsernameNotIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;

如果我们有时候自定义一些基本的sql查询 我们就无需 写什么了 方法了代码大大减少

 

同时我们也可以自定义自己的方式查询通过@Query注解 这里可以参考http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-jpa/ 这篇文章,注意的是JPA 所以@query里面的内容是HQL 如果是mongodb那么语法就是mongodb的查询语法 neo4j就是neo4j的查询语法 

下面我们只要引入注入该类即可使用

 

1
2
3
4
5
6
7
8
@Service
public class UserService {
 
    @Autowired
    private UserRepository userRepository;
     
    @Autowired
    private RoleRepository roleRepository;

这样定义自己的service层 就可以实现相应的方法方式

 

这里要感谢jeesite这个项目 ,他提供了一种取巧的方法 但是却又能保持原来的那种泛型Dao ,甚至能省掉上面的配置xml里面的Repository 相关的一些配置 

下面是我参照这个项目 实现的一个mongodb的实现

 

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
/**
 * 用户DAO接口
 * @author zhuyuping
 * @version 2013-08-01
 */
 
public interface UserDao extends UserDaoCustom, CrudRepository<User, Long>,QueryDslPredicateExecutor<User>{
 
    User findByUsername(String username);
     
}  
 
/**
 * 用户DAO接口
 * @author zhuyuping
 * @version 2013-08-01
 */
 
interface UserDaoCustom extends BaseDao<User,Long> {
 
}
 
/**
 * 用户DAO接口
 * @author zhuyuping
 * @version 2013-08-01
 */
 
@Repository
class UserDaoImpl extends BaseDaoImpl<User,Long> implements UserDaoCustom {
 
     
}

 

 

最精巧的在BaseDaoImpl这里 这里可以调用了原生的模板 或者sessionfactory jdbcTemplate mongodbTemolate  querydsljdbcTemplate entityManager jdbc ....等等 ,这样不仅可以在dao成中增加一些基本方法 属性 ,更重要的这baseDaoImpl 的注入的上面这些模板可以在上面UserDaoImpl使用 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 *
 *     
 *    
 * @author zhuyuping      
 * @version 1.0    
 * @created 2013-8-14 下午3:28:35
 * @functions:
 */
public abstract class BaseDaoImpl<T extends Serializable,PK extends Serializable> implements BaseDao<T,PK> {
 
    @Resource
    protected MongoTemplate mongoTemplate;
     
    public MongoTemplate getMongoTemplate(){
         
        return mongoTemplate;
    }
     
     
     
     
     
}

ok下面还要值得一提的是 如果你继承了那个分页的 PagingAndSortingRepository

 

使用方式 

1
Page<Address> findByIdIn(Collection<Long> Ids, Pageable pageable);

 

 只需要记住传递一个PageAble 即可 而pageAble  有个默认实现PageRequest 当然你可以自定义实现,然后再controller层获取外部的传递的页码数 构造包装 一下即可


,这里基本知识讲完了 

文档里面有详细介绍,例如排序 等等用法例子 ,对于上面morphia 的那些ORM映射的注解 我们知道spring data 也有的 详细的一些在http://www.infoq.com/cn/articles/spring-data-intro 有介绍,这里需要说一下neo4j 

例如常用的User 与 ROLe关系 这里是简单的权限模型 1 为管理员 0 为普通 的一对一关系

user  role 为neo4j的节点 他们拥有属性 

1
UserRoleRelationship 管理node 之间的关系 @Fetch是类似hibernate级联查询

 

 

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
44
45
46
47
48
49
50
51
52
53
54
import org.springframework.data.neo4j.annotation.Fetch;
import org.springframework.data.neo4j.annotation.GraphId;
import org.springframework.data.neo4j.annotation.Indexed;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.annotation.RelatedTo;
  
@NodeEntity
public class User {
     
    @GraphId
    private Long id;
     
    private String firstName;
    private String lastName;
     
    @Indexed
    private String username;
    private String password;
     
    @Fetch @RelatedTo(type = "HAS_ROLE")
    private Role role;
     
     
}
 
import org.springframework.data.neo4j.annotation.GraphId;
import org.springframework.data.neo4j.annotation.NodeEntity;
  
@NodeEntity
public class Role {
     
    @GraphId
    private Long id;
    private User user;
    private Integer role;
     
    ...getters/setters
}
 
import org.springframework.data.neo4j.annotation.EndNode;
import org.springframework.data.neo4j.annotation.RelationshipEntity;
import org.springframework.data.neo4j.annotation.StartNode;
  
@RelationshipEntity(type = "HAS_ROLE")
public class UserRoleRelationship {
  
    private String description;
     
    @StartNode private User user;
     
    @EndNode private Role role;
  
    ...getters/setters
}

ok 基本知识到此为止

 

下面贴出配置

 

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<?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"
    xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
        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
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
        http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd">
 
    <!-- JPA -->
 
<!--     <jpa:repositories base-package="com.zyp.jpa" /> -->
     
<!--     <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> -->
<!--         <property name="dataSource"> -->
<!--             <jdbc:embedded-database type="HSQL" /> -->
<!--         </property> -->
<!--         <property name="persistenceUnitName" value="default" /> -->
<!--         <property name="jpaVendorAdapter"> -->
<!--             <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> -->
<!--                 <property name="database" value="HSQL" /> -->
<!--                 <property name="generateDdl" value="true" />  -->
<!--             </bean> -->
<!--         </property> -->
<!--         <property name="jpaProperties"> -->
<!--             <props> -->
<!--                 <prop key="javax.persistence.validation.mode">none</prop> -->
<!--             </props> -->
<!--         </property> -->
<!--     </bean> -->
     
<!--     <bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> -->
<!--         <property name="entityManagerFactory" ref="entityManagerFactory" /> -->
<!--     </bean> -->
     
    <!-- Neo4J -->
     
<!--     <neo4j:config storeDirectory="/WEB-INF/zhuyuping.db"/> -->
<!--     <neo4j:repositories base-package="com.zyp.repo.neo4j" /> -->
     
    <!-- mongodb -->
     
    <mongo:repositories base-package="com.zyp.mongo" />
    <!-- MongoDBhost="${app.config.mongo.host}" port="${app.config.mongo.port}"  -->
     <mongo:mongo id="mongo" replica-set="localhost:27017">
        <!-- 一些连接属性的设置 -->   
        <mongo: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>
   <mongo:mapping-converter id="mongoConverter" base-package="com.zyp.mongo.model" />
 
 
 
<!--     <bean id="userCredentials" class="org.springframework.data.authentication.UserCredentials"> -->
<!--         <constructor-arg name="username" value="${app.config.mongo.user}" /> -->
<!--     <constructor-arg name="password" value="${app.config.mongo.password}" /> -->
<!--     </bean> -->
    <!-- mongo的工厂,通过它来取得mongo实例,dbname为mongodb的数据库名,没有的话会自动创建 -->
<!--      <mongo:db-factory dbname="test" mongo-ref="mongo" username="${app.config.mongo.user}" password="${app.config.mongo.password}"/>  -->
    <mongo:db-factory id="mongoDbFactory" host="localhost"
    port="27017" dbname="${app.config.mongo.databasename}" />
    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<!--     <constructor-arg> -->
<!--         <mongo:db-factory /> -->
<!--     </constructor-arg> -->
<!--         <constructor-arg ref="mongo" /> -->
<!--     <constructor-arg value="hostels" /> -->
<!--    <constructor-arg ref="mongo" /> -->
<!--     <constructor-arg name="databaseName" value="${app.config.mongo.databasename}" /> -->
      <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
    <constructor-arg  name="mongoConverter" ref="mongoConverter"/>
<!--     <constructor-arg ref="userCredentials" /> -->
    </bean>
     
<!--     <mongo:mapping-converter base-package="com.zyp.mongo.model"  id="mappingMongoConverter"/> -->
     
    <!-- mongodb bean的仓库目录,会自动扫描扩展了MongoRepository接口的接口进行注入 -->
    
<!--  <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>   -->
    
<!--  <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>   -->
 
 
     
 
</beans>

其实每一种数据源 ,只要配置2件东西即可

 

 

1
2
<!--     <neo4j:config storeDirectory="/WEB-INF/zhuyuping.db"/> -->
<!--     <neo4j:repositories base-package="com.zyp.repo.neo4j" /> -->

例如第一条就是配置数据源 数据相关的 mongodb 就配置mongodb相关的需要 JPA就配置jpa相关的实体管理器的相关 ,第二2个 是个扫描器 也就是  他的作用就是使我们上面吧实现的那些repo接口 包括加入注解的实体类 实现ORM映射  同时这些repo被spring data 加入spring容器中,并且交给spring data 映射转换 管理 

这些mongodb的有些混乱 请参考网上的一些教程使用,我只是注释了一些 比如mongodb授权验证 等等一些,便于以后使用 ,当初就注释了 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics