|
1 |
| -# graphql-jpa-query |
| 1 | +GraphQL Query for JPA Entity Model |
| 2 | +=============== |
| 3 | +This library uses [graphql-java v3.0](https://github.com/andimarek/graphql-java) to derive and build the GraphQL schema from JPA Entity Schema provided by entity classes. |
| 4 | + |
| 5 | +It implements a schema builder to generate GraphQL Schema using JPA EntityManager and an JPA Data Fetchers to transform GraphQL queries into JPA queries with flexible type safe criteria expressions and user-friendly SQL query syntax semantics i.e. query by page, , where criteria expressions, select, order by etc. |
| 6 | + |
| 7 | +Dependencies |
| 8 | +----------------- |
| 9 | +This library intends to have the following dependencies: graphql-java, and some javax annotation packages. The tests depend |
| 10 | +on Spring Boot with Hibernate for JPA. |
| 11 | + |
| 12 | +Schema Generation |
| 13 | +----------------- |
| 14 | +The models are introspected using a JPA Entity Manager to auto-generate a GraphQL Schema. After that, you can use GraphQL schema to query your data. |
| 15 | + |
| 16 | +Schema Documentation |
| 17 | +-------------------- |
| 18 | +GraphQL provides a well documented schema for your domain entity model. The Schema Builder produces |
| 19 | +descriptions using `@GraphQLDescription` annotation on Java types and fields. These descriptions will show up in the GraphiQL schema browser to help you provide documented API to end-users. See the GraphiQL section below for more details. |
| 20 | + |
| 21 | +Queries |
| 22 | +-------------- |
| 23 | +This library will wrap each entity into two query fields: |
| 24 | +Each model (say Human or Droid - see tests) will have two representations in the generated schema: |
| 25 | + |
| 26 | +- One that models the Entities directly using singular form, i.e. Human or Droid to get single instance by id. |
| 27 | +- One that wraps the Entity in a pagable request with where criteria expression using Entity pluralized form, i.e. Humans or Droids |
| 28 | + |
| 29 | +Singular Query Wrapper |
| 30 | +-------------- |
| 31 | +You can use simple query, if you need a single object as root of your query. |
| 32 | + |
| 33 | +For Example: |
| 34 | + |
| 35 | + query { |
| 36 | + Human(id: 1) { name } |
| 37 | + } |
| 38 | + |
| 39 | +Will return: |
| 40 | + |
| 41 | + Human: { |
| 42 | + name: "Luke Skywalker" |
| 43 | + } |
| 44 | + |
| 45 | +Query Wrapper with Where Criteria Expressions |
| 46 | +------------------------------------- |
| 47 | +This library supports flexible type safe criteria expressions with user-friendly SQL query syntax semantics using `where` arguments and `select` field to specify the entity graph query with entiy attribute names as a combination of logical expressions like OR, AND, EQ, NE, GT, GE, LT, LR, IN, NIN, IS_NULL, NOT_NULL. |
| 48 | + |
| 49 | +For Example: |
| 50 | + |
| 51 | + query { |
| 52 | + Humans(where: { |
| 53 | + OR: { |
| 54 | + name: { LIKE: "Luke" } |
| 55 | + OR: { |
| 56 | + name: { LIKE: "Darth"} |
| 57 | + } |
| 58 | + } |
| 59 | + }) { |
| 60 | + select { name } |
| 61 | + } |
| 62 | + } |
| 63 | + |
| 64 | +Will return: |
| 65 | + |
| 66 | + { |
| 67 | + Humans: { |
| 68 | + select: [ |
| 69 | + { name: 'Luke Skywalker' }, |
| 70 | + { name: 'Darth Vader' } |
| 71 | + ] |
| 72 | + } |
| 73 | + } |
| 74 | + |
| 75 | +You can use familiar SQL criteria expressions to specify complex criterias to fetch your data from SQL database. If you omit, where argument, all entities will be returned. |
| 76 | + |
| 77 | +Collection Filtering |
| 78 | +-------------------- |
| 79 | +You can specify criteria expressions for one-to-many associations in order to further filter entity by collection attributes: |
| 80 | + |
| 81 | +For Example: |
| 82 | + |
| 83 | + query { |
| 84 | + Humans { |
| 85 | + select { |
| 86 | + name |
| 87 | + friends(where: { |
| 88 | + appearsIn: { |
| 89 | + IN: [A_NEW_HOPE] |
| 90 | + } |
| 91 | + name: { |
| 92 | + LIKE: "Han" |
| 93 | + } |
| 94 | + |
| 95 | + }) { |
| 96 | + id |
| 97 | + name |
| 98 | + } |
| 99 | + } |
| 100 | + } |
| 101 | + } |
| 102 | + |
| 103 | +Will Return: |
| 104 | + |
| 105 | + "Humans": { |
| 106 | + "select": [ |
| 107 | + { |
| 108 | + "name": "Luke Skywalker", |
| 109 | + "friends": [ |
| 110 | + { |
| 111 | + "id": "1002", |
| 112 | + "name": "Han Solo" |
| 113 | + } |
| 114 | + ] |
| 115 | + }, |
| 116 | + { |
| 117 | + "name": "Darth Vader", |
| 118 | + "friends": [] |
| 119 | + }, |
| 120 | + { |
| 121 | + "name": "Han Solo", |
| 122 | + "friends": [] |
| 123 | + }, |
| 124 | + { |
| 125 | + "name": "Leia Organa", |
| 126 | + "friends": [ |
| 127 | + { |
| 128 | + "id": "1002", |
| 129 | + "name": "Han Solo" |
| 130 | + } |
| 131 | + ] |
| 132 | + }, |
| 133 | + { |
| 134 | + "name": "Wilhuff Tarkin", |
| 135 | + "friends": [] |
| 136 | + } |
| 137 | + ] |
| 138 | + } |
| 139 | + |
| 140 | +Reverse Query |
| 141 | +------------- |
| 142 | +You can execute an inverse query to fitler results with a join in many-to-one association with some limitations. If you do this, be aware that only static parameter binding are supported in `where` criteria expressions. |
| 143 | + |
| 144 | +For Example: |
| 145 | + |
| 146 | + query { |
| 147 | + Humans { |
| 148 | + select { |
| 149 | + name |
| 150 | + favoriteDroid(where: {appearsIn: {IN:[A_NEW_HOPE]}}) { |
| 151 | + name |
| 152 | + } |
| 153 | + } |
| 154 | + } |
| 155 | + } |
| 156 | + |
| 157 | +Will Return: |
| 158 | + |
| 159 | + { |
| 160 | + "Humans": { |
| 161 | + "select": [ |
| 162 | + { |
| 163 | + "name": "Luke Skywalker", |
| 164 | + "favoriteDroid": { |
| 165 | + "name": "C-3PO" |
| 166 | + } |
| 167 | + }, |
| 168 | + { |
| 169 | + "name": "Darth Vader", |
| 170 | + "favoriteDroid": { |
| 171 | + "name": "R2-D2" |
| 172 | + } |
| 173 | + } |
| 174 | + ] |
| 175 | + } |
| 176 | + |
| 177 | +Type Safe Arguments |
| 178 | +------------------- |
| 179 | +The JPA Schema builder will derive QraphQL scalar types from JPA model attributes. At runtime, it will validate provided values against the schema. Enum Java types are also translated to QraphQL Enum scalar type. |
| 180 | + |
| 181 | +Pagination |
| 182 | +---------- |
| 183 | +GraphQL does not specify any language or idioms for performing Pagination. This library provides support for pageable queries with `page` argument on pluralized query wrapper. |
| 184 | + |
| 185 | +This allows you to query for the "Page" version of any Entity, and return page metadata i.e. pages and total records count with the select data. |
| 186 | + |
| 187 | +For example: |
| 188 | + |
| 189 | + query { |
| 190 | + Humans(page:{start:0, limit: 3}) { |
| 191 | + pages |
| 192 | + total |
| 193 | + select { |
| 194 | + name |
| 195 | + } |
| 196 | + } |
| 197 | + } |
| 198 | + |
| 199 | +Will return: |
| 200 | + |
| 201 | + { |
| 202 | + "Humans": { |
| 203 | + "pages": 2, |
| 204 | + "total": 5, |
| 205 | + "select": [ |
| 206 | + { |
| 207 | + "name": "Luke Skywalker" |
| 208 | + }, |
| 209 | + { |
| 210 | + "name": "Darth Vader" |
| 211 | + }, |
| 212 | + { |
| 213 | + "name": "Han Solo" |
| 214 | + } |
| 215 | + ] |
| 216 | + } |
| 217 | + |
| 218 | +The JPA DataFetcher implementation will execute an extra query to get the total elements only if you have requested 'pages' or 'total' fields. |
| 219 | + |
| 220 | +Sorting |
| 221 | +------- |
| 222 | + |
| 223 | +Sorting is supported on any field. Simply pass in an 'orderBy' argument with the value of ASC or DESC. Here's an example |
| 224 | +of sorting by name for Human objects. The default sort order can be specified using `GraphQLDefaultSort` annotation on entity field. If sort order is not specified and there is no field with default sort order provided, we will use field annotated with @Id to avoid paging confusions. |
| 225 | + |
| 226 | + query { |
| 227 | + Human { |
| 228 | + name(orderBy: DESC) |
| 229 | + homePlanet |
| 230 | + } |
| 231 | + } |
| 232 | + |
| 233 | +Performance |
| 234 | +----------- |
| 235 | +The JPA DataFetcher implementation will attempt to build dynamic fetch graph in order to optimize query performance and avoid N+1 lazy loading. |
| 236 | + |
| 237 | +GraphiQL Browser |
| 238 | +-------- |
| 239 | + |
| 240 | +GraphiQL (https://github.com/graphql/graphiql) can be used for simple testing. You can launch provided example as Spring Boot Application, and navigate to http://localhost:8080/ to load GraphiQL browser. The collapsed Docs panel can opened by clicking on the button in the upper right corner, that when expanded will show you the running test schema. |
| 241 | + |
| 242 | +You can run GraphQL queries in the left pannel, and hit the run button, and the results should come back in the right |
| 243 | +panel. If your query has variables, there is a minimized panel at the bottom left. Simply click on this to expand, and |
| 244 | +type in your variables as a JSON string (don't forget to quote the keys!). |
| 245 | + |
| 246 | +License |
| 247 | +------- |
| 248 | +Apache License v2.0 |
0 commit comments