English | 中文
NgBatis is a database ORM framework base NebulaGraph + spring-boot, which takes advantage of the mybatis’ fashion development, including some de-factor operations in single table and vertex-edge, like mybatis-plus.
If you prefer JPA, graph-ocean is a good choice.
NgBatis | nebula-java | JDK | Springboot | Beetl |
---|---|---|---|---|
1.3.0 | 3.8.3 | 8 | 2.7.0 | 3.15.10.RELEASE |
1.3.0-jdk17 | 3.8.3 | 17 | 3.0.7 | 3.15.10.RELEASE |
1.2.2 | 3.6.0 | 8 | 2.7.0 | 3.15.10.RELEASE |
1.2.2-jdk17 | 3.6.0 | 17 | 3.0.7 | 3.15.10.RELEASE |
1.2.1 | 3.6.0 | 8 | 2.7.0 | 3.15.10.RELEASE |
1.2.0-jdk17 | 3.6.0 | 17 | 3.0.7 | 3.15.10.RELEASE |
1.2.0 | 3.6.0 | 8 | 2.7.0 | 3.15.10.RELEASE |
1.1.5 | 3.5.0 | 8 | 2.7.0 | 3.1.8.RELEASE |
1.1.4 | 3.5.0 | 8 | 2.7.0 | 3.1.8.RELEASE |
NgBatis | nebula-java | JDK | Springboot | Beetl |
---|---|---|---|---|
1.2.2-jdk17-SNAPSHOT | 3.6.0 | 17 | 3.0.7 | 3.15.10.RELEASE |
1.2.2-SNAPSHOT | 3.6.0 | 8 | 2.7.0 | 3.15.10.RELEASE |
The third-party dependencies may differ within the same snapshot version.
You could refer to ngbatis-demo in this repo.
Include in your pom.xml
<dependency>
<groupId>org.nebula-contrib</groupId>
<artifactId>ngbatis</artifactId>
<version>1.3.0</version>
</dependency>
implementation 'org.nebula-contrib:ngbatis:1.3.0'
Referring to ngbatis-demo, which was smoothly integrated with spring-boot. The API examples could be found under the test of it for all features of ngbatis.
Configure the NebulaGraph Database
Configure application.yml
with the host and credential to enable access to the NebulaGraph Cluster.
nebula:
ngbatis:
session-life-length: 300000 # since v1.1.2
check-fixed-rate: 300000 # since v1.1.2
# space name needs to be informed through annotations(@Space) or xml(space="test")
# default false(false: Session pool map will not be initialized)
use-session-pool: false # since v1.1.2
hosts: 127.0.0.1:19669, 127.0.0.1:9669
username: root
password: nebula
space: test
pool-config:
min-conns-size: 0
max-conns-size: 10
timeout: 0
idle-time: 0
interval-idle: -1
wait-time: 0
min-cluster-health-rate: 1.0
enable-ssl: false
@SpringBootApplication(scanBasePackages = { "org.nebula", "your.domain"})
public class YourApplication {
public static void main(String[] args) {
new SpringApplication(YourApplication.class).run(args);
}
}
If SpringCloud is used in your project, please use
@ComponentScan( basePackages = {"org.nebula.contrib", "your.domain"} )
instead.
package ye.weicheng.ngbatis.demo.repository;
import ye.weicheng.ngbatis.demo.pojo.Person;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface TestRepository {
// new features from v1.2.0
Integer returnAge(@Param("person")Person person);
Person selectPerson();
Person selectByPerson(Person person);
List<Person> selectAgeGt(Integer age);
List<String> selectListString();
List<Map> selectPersonsMap();
Map<String, Object> selectTriple();
}
resource/mapper/TestRepository.xml
<mapper
namespace=
"ye.weicheng.ngbatis.demo.repository.TestRepository"
>
<!-- new features from v1.2.0 start -->
<nGQL id="include-test-value">
${myInt}
</nGQL>
<nGQL id="ngql-return-age">
RETURN @ng.include('include-test-value',{'myInt':age});
</nGQL>
<!--
The same as:
RETURN ${person.age};
You can try extracting more common and meaningful scripts.
-->
<select id="returnAge" resultType="java.lang.Integer">
@ng.include('ngql-return-age',person);
</select>
<!-- new features from v1.2.0 end -->
<select id="selectPerson" resultType="ye.weicheng.ngbatis.demo.pojo.Person">
match (v:person) return v.person.name as name, v.person.age as age limit 1
</select>
<select id="selectAgeGt" resultType="ye.weicheng.ngbatis.demo.pojo.Person">
MATCH (n: person)
WHERE n.person.age > $p0
RETURN n
LIMIT 100
</select>
<select id="selectByPerson" resultType="ye.weicheng.ngbatis.demo.pojo.Person">
MATCH (n: person)
WHERE n.person.name == $p0.name
RETURN n
LIMIT 100
</select>
<select id="selectListString" resultType="java.lang.String">
match (v:person) return v.person.name as name limit 100
</select>
<select id="selectPersonsMap" resultType="java.util.Map">
match (v:person) return v.person.name as name, v.person.age as age limit 100
</select>
<select id="selectTriple" resultType="java.util.Map">
MATCH (n: person)-[r: like]->(n2: person)
RETURN n, r, n2
LIMIT 100
</select>
<!--
More complex `nGQL` may need to be fully tested.
The two-layer object data structure of the project I am currently using is also satisfying.
`Path` is not yet supported because it can basically be handled by the `n, r, n2` structure in development.
-->
</mapper>
package com.example.model.vertex.Person;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
@Data
@Table(name = "person")
public class Person {
@Id
private String name;
private Integer age;
}
package com.example.model.edge.Like;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.Data;
import javax.persistence.Table;
@Data
@Table(name = "like")
@NoArgsConstructor
@AllArgsConstructor
public class Like {
private Double likeness;
}
package com.example.dao;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
import com.example.model.vertex.Person;
public interface PersonDao extends NebulaDaoBasic<Person, String>{}
Note, this is a mandatory requirement.
<mapper
namespace=
"com.example.dao.PersonDao"
>
</mapper>
package com.example.service;
import org.nebula.contrib.ngbatis.utils.Page;
import com.example.dao.PersonDao;
import com.example.model.vertex.Person;
import com.example.model.edge.Like;
@Service
public class PersonServiceImpl {
@Autowired private PersonDao dao;
public void demos() {
// Implement two node insertions
Person tom = new Person();
tom.setName("Tom");
dao.insert( tom );
Person jerry = new Person();
jerry.setName( "Jerry" );
dao.insert( jerry );
// Establishing the relationship between two nodes
Like like = new Like( 0.99999 );
dao.insertEdge( tom, like, jerry );
// Find people who like jerry
String jerryId = jerry.getName();
List<Person> whoLikeJerry = dao.listStartNodes( Like.class, jerryId );
// Find the only people who like jerry, Non-Unique Times Error。(Limited to scenarios where there is only one upstream for a given relationship)
Person tom = dao.startNode( Like.class, jerryId );
// See the Like relationship between Tom and Jerry
String tomId = tom.getName();
Boolean tomLikeJerry = dao.existsEdge( tomId, Like.class, jerryId ); // true
Boolean jerryLikeTom = dao.existsEdge( jerryId, Like.class, tomId ); // false
// Poor Tom
// Find all information by Tom's name
Person tomDb = dao.selectById( "Tom" );
// Search by page
Page<Person> page = new Page<>();
List<Person> personPage = dao.selectPage( page );
page.getTotal(); // 2 rows, Tom and Jerry
Boolean theyAreFamily = page.getRows() == personPage; // true
// The story always wants to have a good ending
dao.insertEdge( jerry, like, tom );
// More base class operations are still under development;Expectations
}
}
GraphBaseVertex
class identifier as a vertex entity@Tag
indicates the Tag of the vertex entity@GraphId
indicates the type of the point entity id (optional)
@Tag(name = "player")
public class Player extends GraphBaseVertex {
@GraphId(type = IdType.STRING)
private String id;
private String name;
private Integer age;
...
}
Specific reference ye.weicheng.ngbatis.demo.pojo.vertex
vertex entities under the package sample.
GraphBaseEdge
class to identify edge entities@EdgeType
indicates the type of the edge entity@Id
(Optional, if the uniqueness of an edge of the same type between two nodes is determined by the source node id and the destination node id, the current attribute can be omitted)@SrcId
(optional, if you do not need to obtain the source node id of the relationship, you can omit the current attribute)@DstId
(Optional, if you do not need to get the target node id of the relationship, you can omit the current attribute)
@EdgeType(name = "serve")
public class Serve extends GraphBaseEdge {
@Id
private Long rank;
@SrcId
private String srcId;
@DstId
private String dstId;
@Column(name = "start_year")
private Integer startYear;
@Column(name = "end_year")
private Integer endYear;
...
}
Specific reference ye.weicheng.ngbatis.demo.pojo.edge
edge entities under the package sample.
API | 用法说明 |
---|---|
queryIdsByProperties() | Query a collection of vertex ids for a particular Tag or attribute |
queryVertexById() | Query a single vertex for a specific vertex Id |
queryVertexByTag() | Query a collection of vertices for a specific Tag |
queryVertexByProperties() | Query a collection of vertexes for a specific property |
queryAllAdjacentVertex(Class<?>... edgeClass) | Query a collection of all neighboring vertexes of a particular vertex, specifying one or more edge types that connect the two vertexes |
queryIncomingAdjacentVertex(Class<?>... edgeClass) | Query the set of adjacent vertexes in the direction of the incoming edge of a particular vertex, specifying one or more edge types that connect two vertexes |
queryOutgoingAdjacentVertex(Class<?>... edgeClass) | Query the set of adjacent vertexes in the direction of the edge of a particular vertex, specifying one or more edge types that connect two vertexes |
queryNeighborIdsWithHopById(int m, int n, Class<?>... edgeClass) | Query a collection of vertex ids within a specified number of hops for a particular vertex, specifying one or more edge types that connect two vertexes |
queryConnectedEdgesById(Direction direction) | Query the set of all edges associated with a particular vertex, specifying the direction and type of the edge |
queryPathFromVertex(Direction direction) | Query the collection of all paths associated with a particular vertex, specifying the direction of the edge |
queryFixedLengthPathFromVertex(Integer maxHop, Direction direction, Class<?>... edgeClass) | Query a set of fixed-length paths from a specific vertex, specifying the maximum number of steps, the direction of the edge, and the type of the edge |
queryVariableLengthPathFromVertex(Integer minHop, Integer maxHop, Direction direction, Class<?>... edgeClass) | Query a set of variable-length paths from a specific vertex, specifying the minimum number of steps, the maximum number of steps, the direction of the edge, and the type of the edge |
queryShortestPathFromSrcAndDst(Integer maxHop, Direction direction, T v2) | Query any shortest path from a specific vertex, specifying the number of steps, the direction of the edge, and the end vertex entity |
queryAllShortestPathsFromSrcAndDst(Integer maxHop, Direction direction, T v2) | Query the set of all shortest paths from this vertex, specifying the number of steps, the direction of the edge, and the end vertex entity |
queryVertexCountByTag() | Query the number of vertexes for a specific Tag |
For specific implementation, see the point entity base class GraphBaseVertex
under the org.nebula.contrib.ngbatis.base
package.
API | 用法说明 |
---|---|
queryEdgeByType(Direction direction) | Query a set of edges of a specific type and direction |
queryEdgeWithSrcAndDstByProperties(T srcVertex, Direction direction, T dstVertex) | Query a set of edges for a particular property |
queryEdgePropertiesBySrcAndDstId() | Query a set of edges for a specific always vertex id |
queryEdgeCountByType() | Query the number of edges for a specific Type |
For specific implementation, see the point entity base class GraphBaseEdge
under the org.nebula.contrib.ngbatis.base
package.
@Test
public void testVertex(){
Player srcPlayer = new Player();
//Query all Player vertices that meet the condition name = "Vince Carter"
srcPlayer.setName("Vince Carter");
List<Player> vertices = player.queryVertexByProperties();
}
@Test
public void testEdge(){
Serve serve = new Serve();
//Query the Server edge whose starting point ID is player100 and the end point ID is team204.
serve.setSrcId("player100");
serve.setDstId("team204");
Serve edge = serve.queryEdgeWithSrcAndDstByProperties();
//Query the edges of Serve type and direction "->"
List<Serve> edges = serve.queryEdgeByType(Direction.NULL);
}
For specific usage examples of each direct inspection method, please refer to the NebulaGraphBasicTests
test class in ngbatis-demo.
NGBATIS is under the Apache License, Version 2.0.