經過四天的奮戰,終於把GraphQL和SpringMVC整合在了一起。這次主要採用的SpringMVC,和hibernate框架。一些和項目相關的簡單的配置這裏不做過多的介紹。話不多說,直接上代碼吧。
定義了兩個實體類
User.java
@Entity
@Table(name = "info")
public class Info {
private int id;
private String truename;
private String address;
private User user;
public Info(int id, String truename, String address, User user) {
super();
this.id = id;
this.truename = truename;
this.address = address;
this.user = user;
}
public Info() {
}
@Override
public String toString() {
return "Info [id=" + id + ", truename=" + truename + ", address=" + address + ", user=" + user + "]";
}
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTruename() {
return truename;
}
public void setTruename(String truename) {
this.truename = truename;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@OneToOne
@JoinColumn(name = "user")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
User.java
@Entity
@Table(name = "user")
public class User {
private int id;
private String username;
private String password;
public User(int id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public User() {
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
}
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
然後從數據庫中將info數據取出,當時方法名取錯了,不要在意這些細節
public Info getUserInfo(int id) {
Session session = hibernateTemplate.getSessionFactory().getCurrentSession();
String hql = "from Info i where i.id = ?";
Query query = session.createQuery(hql).setParameter(0, id);
Info info = (Info) query.uniqueResult();
System.out.println(info);
return info;
}
以上的這些部分都是實現基本上的在SpringMVC框架上的是實現最基本的獲取數據庫數據,不做過多的介紹,接下來是本次的重頭戲:
新建一個雷,專門用來生成每個實體對應的類型的GraphQLObjectType,這樣每次就可以直接來這個類取,也增加了代碼的複用性,後來去graphql-java中查看了一下源代碼,它應該也是這樣做的:
public class GraphQLObject {
public static GraphQLObjectType user = newObject().name("user")
.field(newFieldDefinition().name("id").type(Scalars.GraphQLInt).build())// 類型一定要與結構類字段的類型相對應
.field(newFieldDefinition().name("username").type(Scalars.GraphQLString).build())
.field(newFieldDefinition().name("password").type(Scalars.GraphQLString).build()).build();
public static GraphQLObjectType info = newObject().name("info")
.field(newFieldDefinition().name("id").type(Scalars.GraphQLInt).build())// 類型一定要與結構類字段的類型相對應
.field(newFieldDefinition().name("truename").type(Scalars.GraphQLString).build())
.field(newFieldDefinition().name("address").type(Scalars.GraphQLString).build())
.field(newFieldDefinition().name("user").type(user).build()).build();
}
然後在查詢對應的方法中生成對應的搜索域和執行搜索就可以了
@Override
public Map<String, Object> getUserInfo(String ghql) {
GraphQLFieldDefinition findforid = GraphQLFieldDefinition.newFieldDefinition().name("info")
.argument(// 這裏用GraphQL些查詢語句時傳入的參數
newArgument().name("id")// 參數名爲id
.type(Scalars.GraphQLInt)// 參數類型
.build())
.type(GraphQLObject.info)// 綁定GraphQL的一個結構,就是上面的那段代碼
.dataFetcher(environment -> {
// 獲取查詢參數
int id = environment.getArgument("id");
return userDAO.getUserInfo(id);
}).build();
GraphQLSchema schema = GraphQLSchema.newSchema().query(newObject().name("_123").field(findforid).build())
.build();
// "{info(id:1){id,truename,address,user{id,username,password}}}";
ExecutionResult re = new GraphQL(schema).execute(ghql);
Map<String, Object> result = (Map<String, Object>) re.getData();
System.out.println(result);
return result;
}
最後將map轉化爲就送數據就可以了;
我在前端的文本框中輸入
"{info(id:1){id,truename,address,user{id,username,password}}}";
就可以得到一下的結果:
{
"info":{
"id":1,
"truename":"123",
"address":"123",
"user":{
"id":1,
"username":"123",
"password":"123"
}
}
}
最後簡單說一下心得體會,這種東西對後端還是比較友好的,畢竟根據一定的條件,就可以返回前端所需要的數據,對後端的維護什麼的還是比較方便的
但是呢,查詢條件對應的接口還是都要有的,本文是以ID爲查找條件,若改爲以truename爲查詢條件則需要在寫一個藉口。
而且這種做法個人感覺有點不太安全,相當於是把後臺的數據,設置是數據庫的數據直接暴露在前臺,感覺不是很安全的樣子。
而且,由於一開始不知道前端會需要查詢結果有哪些,所以在查詢的時候只能將與該信息相關的所有信息都順帶查詢出來供前端選擇,這樣對數據庫的壓力還是很大的,在想有沒有什麼辦法可以將數據查詢出來之後就只接保存在內存或者服務器中,下次在需要就重新調用就好了,可是感覺這樣的話就好像沒有什麼要數據庫的必要了,感覺這個問題還是有必要好好研究或者解決的。
順便提一下,今天下午再整這東西的時候,發現graphql-java在5個小時之前還稍稍更新了一下
文章講的不是很清楚,大家可以看看源碼:http://download.csdn.net/detail/q15150676766/9891144
如果文章中有任何侵犯到您的,望告知[email protected],一定在第一時間刪改。