GraphQL在Java中的应用要解决的第一个问题便是如何根据Java Bean自动生成GraphQL Schema,定义多套基本上是不可接受的,在现有加一些注解还是能忍的。
关系型数据库的解决方案已经做得比较好了,目前Yahoo/Elide应该是做得最好的,结合elide-spring-boot-starter可以轻松完成。虽然文档不详细,但是对基本了解是够了,特点如下(如果考虑其它方案可以一一对比,应该是比elide在便利性上要差一些):
由Java Bean自动生成GraphQL的Schema,无需额外注解;
可以限定顶级访问对象(隐藏一些数据不在顶层);
@Include(rootLevel = true)
无需Repository/Service之类操作DB的代码,结合了RQL,让filter
操作更简单;
定义了比较完善的操作,共6种
其它:有权限管理,实现依据Relay规范
可以看完这些再来跟一些其它方案比较比较(不比了,实在是没得比,Yahoo毕竟曾经是一流互联网企业)。
用例可参考GraphQL初探:Java服务示例及Yahoo/Elide文章中的3.2部分。
很不幸,Elide只是社区大概有句“也许可以通过Hibernate OGM实现”,简单做了尝试,没能做出一个可用的来。
GraphQL-SPQR: Java 8+ API for rapid development of GraphQL services
注意:GraphQL-SPQR可不是只能做NOSQL,放在这里只是说灵活性比较好,可以把组件拆解让NOSQL方案也能使用。
特点:
示例代码见du00cs/graphql-demo(贴代码是不可能的),有一些需要注意的点:
Java bean定义预期是有嵌套、有集合的,记得关掉@Entity
注解,避免hibernate扫描报mapping错误。
import lombok.Data;
import javax.persistence.*;
import java.util.List;
@Data
// @Entity 别加,加了之后hibernate会按关系表扫描,报列无法mapping的错误
@Table(name = "places")
public class Place {
@Id
@GeneratedValue
String id;
String category;
String name;
List<String> alias;
List<Level> levels;
public Place(String name, List<String> alias) {
this.name = name;
this.alias = alias;
}
}
import lombok.Data;
@Data
public class Level {
String name;
}
需要关注的核心都在Service代码的注解中
import io.leangen.graphql.annotations.GraphQLMutation;
import io.leangen.graphql.annotations.GraphQLQuery;
import io.leangen.graphql.spqr.spring.annotations.GraphQLApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Collection;
@GraphQLApi
@Service
public class PlaceService {
@Autowired PlaceRepository repo;
@GraphQLMutation
public Place createPlace(Place place) {
return repo.save(place);
}
@GraphQLQuery
public Collection<Place> allPlaces() {
return repo.findAll();
}
}