ApacheCayenne 的架构生成器 类
Schema Generator for ApacheCayenne classes
我正在尝试使用 SPQR 从 Cayenne 生成的 class 生成 GraphQL 模式。
卡宴 class 看起来像这样
public class MyCayenneClass {
public static final Property<Integer> A_PROPERTY = Property.create("aProperty", Integer.class);
public static final Property<Integer> ANOTHER_PROPERTY = Property.create("anotherProperty", String.class);
public void setAProperty(Integer aProperty) {
writeProperty("aProperty", aProperty);
}
public Integer getAProperty() {
return (Integer)readProperty("aProperty");
}
public void setAnotherProperty(String anotherProperty) {
writeProperty("anotherProperty", anotherProperty);
}
public String getAnotherProperty() {
return (String)readProperty("anotherProperty");
}
}
由于 class 不是简单的 POJO,SPQR 抛出异常并且未生成架构。
Error: QUERY_ROOT fields must be an object with field names as keys or a function which returns such an object.
最好的方法是什么(不修改 cayenne class(即注释方法)?
GraphQLEndPoing.java
@WebServlet(urlPatterns = "/graphql")
public class GraphQLEndpoint extends SimpleGraphQLServlet {
public GraphQLEndpoint() {
super(buildSchema());
}
//This method used SPQR
private static GraphQLSchema buildSchema() {
GraphQLSchema schemaGenerator = new GraphQLSchemaGenerator()
.withOperationsFromSingletons(myRepository) //register the beans
.generate();
return schemaGenerator;
}
private static final MyRepository myRepository;
static {
myRepository= new MyRepository ();
}
}
MyRepository.java
public class MyRepository{
private MyLibService libService;
@GraphQLQuery
public MyCayenneClass find(Integer id) {
List<MyCayenneClass> myList= libService.fetchById(new Integer[] {id});
return myList.get(0);
}
}
*仅供参考。如果我声明模式。代码将正常工作
schema {
query: Query
}
type Query {
find(id: Int): MyCayenneClass
}
type ConcContract {
id: ID
aProperty: Int
anotherProperty: String
}
从 SPQR 的角度来看,这与 POJO 并没有什么不同,因为 SPQR 只关心类型。
默认情况下,对于所有嵌套的 classes(在您的情况下为 MyCayenneClass
),所有看起来像 getter 的内容都会被公开。对于 top-level classes(MyRepository
在你的情况下),默认只公开带注释的方法。并且至少必须公开一个 top-level 方法,否则您的架构无效。
错误,就目前而言,只是意味着没有发现单个 top-level 查询。我看到 @GraphQLQuery
注释被注释掉了。那是故意的吗?使用默认配置,这不会公开任何查询。
您可以注册一个不同的 ResolverBuilder
,例如PublicResolverBuilder
(或您自己的 implementation/extension)如果您想公开 un-annotated 方法。
例如
generator.withOperationsFromSingleton(new MyRepository(), new PublicResolverBuilder())
这将公开来自 class 的所有 public 方法。
这是我在 v0.9.6 上尝试过的一个稍微简化的例子,它似乎按预期工作(我知道你使用的是错误文本中的一个相当旧的版本)。
public class MyRepository {
@GraphQLQuery //not commented out
public MyCayenneClass find(Integer in) {
return new MyCayenneClass();
}
}
// extends CayenneDataObject because I don't know where to get the
// writeProperty and readProperty from
// but shouldn't change anything from SPQR's perspective
public class MyCayenneClass extends CayenneDataObject {
public static final Property<Integer> A_PROPERTY = Property.create("aProperty", Integer.class);
public static final Property<String> ANOTHER_PROPERTY = Property.create("anotherProperty", String.class);
public void setAProperty(Integer aProperty) {
writeProperty("aProperty", aProperty);
}
public Integer getAProperty() {
return (Integer)readProperty("aProperty");
}
public void setAnotherProperty(String anotherProperty) {
writeProperty("anotherProperty", anotherProperty);
}
public String getAnotherProperty() {
return (String)readProperty("anotherProperty");
}
}
您可以应用更多自定义,具体取决于您最终需要的内容,但从目前的问题来看,您似乎不需要任何额外的...
要覆盖用于嵌套 class 的 ResolverBuilder
,您有 2 个选项。
1) 全局注册,所以所有嵌套类型都使用它:
generator.withNestedResolverBuilders(customBuilder)
2) 或按类型:
.withNestedResolverBuildersForType(MyCayenneClass.class, new BeanResolverBuilder())
但这很少需要...
我正在尝试使用 SPQR 从 Cayenne 生成的 class 生成 GraphQL 模式。 卡宴 class 看起来像这样
public class MyCayenneClass {
public static final Property<Integer> A_PROPERTY = Property.create("aProperty", Integer.class);
public static final Property<Integer> ANOTHER_PROPERTY = Property.create("anotherProperty", String.class);
public void setAProperty(Integer aProperty) {
writeProperty("aProperty", aProperty);
}
public Integer getAProperty() {
return (Integer)readProperty("aProperty");
}
public void setAnotherProperty(String anotherProperty) {
writeProperty("anotherProperty", anotherProperty);
}
public String getAnotherProperty() {
return (String)readProperty("anotherProperty");
}
}
由于 class 不是简单的 POJO,SPQR 抛出异常并且未生成架构。
Error: QUERY_ROOT fields must be an object with field names as keys or a function which returns such an object.
最好的方法是什么(不修改 cayenne class(即注释方法)?
GraphQLEndPoing.java
@WebServlet(urlPatterns = "/graphql")
public class GraphQLEndpoint extends SimpleGraphQLServlet {
public GraphQLEndpoint() {
super(buildSchema());
}
//This method used SPQR
private static GraphQLSchema buildSchema() {
GraphQLSchema schemaGenerator = new GraphQLSchemaGenerator()
.withOperationsFromSingletons(myRepository) //register the beans
.generate();
return schemaGenerator;
}
private static final MyRepository myRepository;
static {
myRepository= new MyRepository ();
}
}
MyRepository.java
public class MyRepository{
private MyLibService libService;
@GraphQLQuery
public MyCayenneClass find(Integer id) {
List<MyCayenneClass> myList= libService.fetchById(new Integer[] {id});
return myList.get(0);
}
}
*仅供参考。如果我声明模式。代码将正常工作
schema {
query: Query
}
type Query {
find(id: Int): MyCayenneClass
}
type ConcContract {
id: ID
aProperty: Int
anotherProperty: String
}
从 SPQR 的角度来看,这与 POJO 并没有什么不同,因为 SPQR 只关心类型。
默认情况下,对于所有嵌套的 classes(在您的情况下为 MyCayenneClass
),所有看起来像 getter 的内容都会被公开。对于 top-level classes(MyRepository
在你的情况下),默认只公开带注释的方法。并且至少必须公开一个 top-level 方法,否则您的架构无效。
错误,就目前而言,只是意味着没有发现单个 top-level 查询。我看到 @GraphQLQuery
注释被注释掉了。那是故意的吗?使用默认配置,这不会公开任何查询。
您可以注册一个不同的 ResolverBuilder
,例如PublicResolverBuilder
(或您自己的 implementation/extension)如果您想公开 un-annotated 方法。
例如
generator.withOperationsFromSingleton(new MyRepository(), new PublicResolverBuilder())
这将公开来自 class 的所有 public 方法。
这是我在 v0.9.6 上尝试过的一个稍微简化的例子,它似乎按预期工作(我知道你使用的是错误文本中的一个相当旧的版本)。
public class MyRepository {
@GraphQLQuery //not commented out
public MyCayenneClass find(Integer in) {
return new MyCayenneClass();
}
}
// extends CayenneDataObject because I don't know where to get the
// writeProperty and readProperty from
// but shouldn't change anything from SPQR's perspective
public class MyCayenneClass extends CayenneDataObject {
public static final Property<Integer> A_PROPERTY = Property.create("aProperty", Integer.class);
public static final Property<String> ANOTHER_PROPERTY = Property.create("anotherProperty", String.class);
public void setAProperty(Integer aProperty) {
writeProperty("aProperty", aProperty);
}
public Integer getAProperty() {
return (Integer)readProperty("aProperty");
}
public void setAnotherProperty(String anotherProperty) {
writeProperty("anotherProperty", anotherProperty);
}
public String getAnotherProperty() {
return (String)readProperty("anotherProperty");
}
}
您可以应用更多自定义,具体取决于您最终需要的内容,但从目前的问题来看,您似乎不需要任何额外的...
要覆盖用于嵌套 class 的 ResolverBuilder
,您有 2 个选项。
1) 全局注册,所以所有嵌套类型都使用它:
generator.withNestedResolverBuilders(customBuilder)
2) 或按类型:
.withNestedResolverBuildersForType(MyCayenneClass.class, new BeanResolverBuilder())
但这很少需要...