diff --git a/.idea/ApifoxUploaderProjectSetting.xml b/.idea/ApifoxUploaderProjectSetting.xml
new file mode 100644
index 0000000..5df016c
--- /dev/null
+++ b/.idea/ApifoxUploaderProjectSetting.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..55f8480
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
index 45b0fd7..a6ba966 100644
--- a/.idea/dataSources.xml
+++ b/.idea/dataSources.xml
@@ -13,5 +13,18 @@
$ProjectFileDir$
+
+ mysql.8
+ true
+ com.mysql.cj.jdbc.Driver
+ jdbc:mysql://localhost:3307/main?useSSL=false&allowPublicKeyRetrieval=true
+
+
+
+
+
+
+ $ProjectFileDir$
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 0068521..42f6774 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,19 +16,9 @@
3.4.0
2024.0.0
5.8.32
+ 7.1.4
-
-
- central
- https://repo1.maven.org/maven2/
-
-
- jitpack.io
- https://jitpack.io
-
-
-
org.springframework.boot
@@ -38,6 +28,15 @@
org.springframework.boot
spring-boot-configuration-processor
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ com.yahoo.elide
+ elide-spring-boot-starter
+ ${elide.version}
+
cn.hutool
@@ -45,12 +44,6 @@
${hutool.version}
-
- com.github.Tencent
- APIJSON
- 7.7.0
-
-
com.mysql
mysql-connector-j
diff --git a/src/main/java/com/lanyuanxiaoyao/server/api/ApiController.java b/src/main/java/com/lanyuanxiaoyao/server/api/ApiController.java
deleted file mode 100644
index 515eab8..0000000
--- a/src/main/java/com/lanyuanxiaoyao/server/api/ApiController.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.lanyuanxiaoyao.server.api;
-
-import apijson.RequestMethod;
-import apijson.StringUtil;
-import jakarta.servlet.http.HttpSession;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * @author lanyuanxiaoyao
- * @since 2025-03-03
- */
-@Slf4j
-@RestController
-@RequestMapping("api")
-public class ApiController {
- private String parse(RequestMethod method, String request) {
- return new ApiParser(method)
- .setNeedVerify(false)
- .parse(request);
- }
-
- @RequestMapping("{method}")
- public String crud(@PathVariable("method") String method, @RequestBody String request) {
- return parse(RequestMethod.valueOf(StringUtil.toUpperCase(method)), request);
- }
-}
diff --git a/src/main/java/com/lanyuanxiaoyao/server/api/ApiParser.java b/src/main/java/com/lanyuanxiaoyao/server/api/ApiParser.java
deleted file mode 100644
index e6f1636..0000000
--- a/src/main/java/com/lanyuanxiaoyao/server/api/ApiParser.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package com.lanyuanxiaoyao.server.api;
-
-import apijson.NotNull;
-import apijson.RequestMethod;
-import apijson.orm.AbstractFunctionParser;
-import apijson.orm.AbstractObjectParser;
-import apijson.orm.AbstractParser;
-import apijson.orm.AbstractSQLConfig;
-import apijson.orm.AbstractSQLExecutor;
-import apijson.orm.AbstractVerifier;
-import apijson.orm.FunctionParser;
-import apijson.orm.Join;
-import apijson.orm.ObjectParser;
-import apijson.orm.Parser;
-import apijson.orm.SQLConfig;
-import apijson.orm.SQLExecutor;
-import apijson.orm.Verifier;
-import com.alibaba.fastjson.JSONObject;
-import java.util.List;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * @author lanyuanxiaoyao
- * @since 2025-03-03
- */
-@SuppressWarnings("LombokGetterMayBeUsed")
-@Slf4j
-public class ApiParser extends AbstractParser {
- @Getter
- private FunctionParser functionParser;
-
- public ApiParser() {
- super();
- }
-
- public ApiParser(RequestMethod method) {
- super(method);
- }
-
- @Override
- public Object onFunctionParse(String key, String function, String parentPath, String currentName, JSONObject currentObject, boolean containRaw) throws Exception {
- if (functionParser == null) {
- functionParser = createFunctionParser();
- functionParser.setMethod(getMethod());
- functionParser.setTag(getTag());
- functionParser.setVersion(getVersion());
- functionParser.setRequest(requestObject);
- }
- functionParser.setKey(key);
- functionParser.setParentPath(parentPath);
- functionParser.setCurrentName(currentName);
- functionParser.setCurrentObject(currentObject);
-
- return functionParser.invoke(function, currentObject, containRaw);
- }
-
- @Override
- public ObjectParser createObjectParser(JSONObject request, String parentPath, SQLConfig arrayConfig, boolean isSubquery, boolean isTable, boolean isArrayMainTable) throws Exception {
- return new ApiObjectParser(request, parentPath, arrayConfig, isSubquery, isTable, isArrayMainTable).setParser(this);
- }
-
- @Override
- public Parser createParser() {
- return new ApiParser();
- }
-
- @Override
- public FunctionParser createFunctionParser() {
- return new ApiFunctionParser();
- }
-
- @Override
- public SQLConfig createSQLConfig() {
- return new ApiSQLConfig();
- }
-
- @Override
- public SQLExecutor createSQLExecutor() {
- return new ApiSQLExecutor();
- }
-
- @Override
- public Verifier createVerifier() {
- return new ApiVerifier();
- }
-
- public static final class ApiVerifier extends AbstractVerifier {
- @Override
- public Parser createParser() {
- return new ApiParser();
- }
- }
-
- public static final class ApiSQLConfig extends AbstractSQLConfig {
- static {
- DEFAULT_DATABASE = DATABASE_MYSQL;
- DEFAULT_SCHEMA = "main";
-
- TABLE_KEY_MAP.put("HostAssets", "host_assets");
- }
-
- public ApiSQLConfig() {
- super(RequestMethod.GET);
- }
-
- public ApiSQLConfig(RequestMethod method) {
- super(method);
- }
-
- public ApiSQLConfig(RequestMethod method, String table) {
- super(method, table);
- }
-
- public static SQLConfig newSQLConfig(RequestMethod method, String table, String alias, com.alibaba.fastjson.JSONObject request, List joinList, boolean isProcedure) throws Exception {
- return AbstractSQLConfig.newSQLConfig(method, table, alias, request, joinList, isProcedure, new SimpleCallback<>() {
- @Override
- public SQLConfig getSQLConfig(RequestMethod method, String database, String schema, String datasource, String table) {
- return new ApiSQLConfig(method, table);
- }
- });
- }
-
- @Override
- public String getDBVersion() {
- return "8.4.4";
- }
-
- @Override
- public String getDBUri() {
- return "jdbc:mysql://192.168.100.140:3307/main?useSSL=false&allowPublicKeyRetrieval=true";
- }
-
- @Override
- public String getDBAccount() {
- return "test";
- }
-
- @Override
- public String getDBPassword() {
- return "test";
- }
- }
-
- public static final class ApiFunctionParser extends AbstractFunctionParser {
- }
-
- public static final class ApiSQLExecutor extends AbstractSQLExecutor {
- static {
- try {
- Class.forName("com.mysql.cj.jdbc.Driver");
- } catch (ClassNotFoundException e) {
- log.error(e.getMessage(), e);
- }
- }
- }
-
- public static final class ApiObjectParser extends AbstractObjectParser {
- public ApiObjectParser(@NotNull JSONObject request, String parentPath, SQLConfig arrayConfig, boolean isSubquery, boolean isTable, boolean isArrayMainTable) throws Exception {
- super(request, parentPath, arrayConfig, isSubquery, isTable, isArrayMainTable);
- }
-
- @Override
- public SQLConfig newSQLConfig(RequestMethod method, String table, String alias, JSONObject request, List joinList, boolean isProcedure) throws Exception {
- return ApiSQLConfig.newSQLConfig(method, table, alias, request, joinList, isProcedure);
- }
- }
-}
diff --git a/src/main/java/com/lanyuanxiaoyao/server/entity/School.java b/src/main/java/com/lanyuanxiaoyao/server/entity/School.java
new file mode 100644
index 0000000..f0b5c83
--- /dev/null
+++ b/src/main/java/com/lanyuanxiaoyao/server/entity/School.java
@@ -0,0 +1,36 @@
+package com.lanyuanxiaoyao.server.entity;
+
+import com.yahoo.elide.annotation.Include;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.OneToMany;
+import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.hibernate.annotations.DynamicUpdate;
+
+/**
+ * @author lanyuanxiaoyao
+ * @version 20250304
+ */
+@Getter
+@Setter
+@ToString
+@Entity
+@DynamicUpdate
+@Include
+public class School {
+ @Id
+ @GeneratedValue(strategy = GenerationType.UUID)
+ private String id;
+ @Column(nullable = false)
+ private String name;
+ @OneToMany(fetch = FetchType.LAZY, mappedBy = "school")
+ @ToString.Exclude
+ private List users;
+}
diff --git a/src/main/java/com/lanyuanxiaoyao/server/entity/User.java b/src/main/java/com/lanyuanxiaoyao/server/entity/User.java
new file mode 100644
index 0000000..da17426
--- /dev/null
+++ b/src/main/java/com/lanyuanxiaoyao/server/entity/User.java
@@ -0,0 +1,41 @@
+package com.lanyuanxiaoyao.server.entity;
+
+import com.yahoo.elide.annotation.Include;
+import jakarta.persistence.Column;
+import jakarta.persistence.ConstraintMode;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.hibernate.annotations.DynamicUpdate;
+
+/**
+ * @author lanyuanxiaoyao
+ * @version 20250304
+ */
+@Getter
+@Setter
+@ToString
+@Entity
+@DynamicUpdate
+@Include
+public class User {
+ @Id
+ @GeneratedValue(strategy = GenerationType.UUID)
+ private String id;
+ @Column(unique = true, nullable = false)
+ private String username;
+ @Column(nullable = false)
+ private String password;
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
+ @ToString.Exclude
+ private School school;
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index e69de29..729421f 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -0,0 +1,22 @@
+spring:
+ datasource:
+ url: jdbc:mysql://localhost:3307/main?useSSL=false&allowPublicKeyRetrieval=true
+ username: test
+ password: test
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ jpa:
+ show-sql: true
+ generate-ddl: true
+elide:
+ json-api:
+ enabled: true
+ path: /json
+logging:
+ level:
+ com:
+ yahoo:
+ elide:
+ datastores:
+ jpql:
+ query:
+ DefaultQueryLogger: debug
\ No newline at end of file
diff --git a/src/test/resources/school.http b/src/test/resources/school.http
new file mode 100644
index 0000000..0ca6725
--- /dev/null
+++ b/src/test/resources/school.http
@@ -0,0 +1,33 @@
+### Query
+GET http://localhost:8080/json/school
+Content-Type: application/vnd.api+json
+
+### Create
+POST http://localhost:8080/json/school
+Content-Type: application/vnd.api+json
+
+{
+ "data": {
+ "type": "school",
+ "attributes": {
+ "name": "school_1"
+ }
+ }
+}
+
+### Modify
+PATCH http://localhost:8080/json/school/f424701d-dc94-42be-b2e6-79221b18ee7d
+Content-Type: application/vnd.api+json
+
+{
+ "data": {
+ "type": "user",
+ "id": "f424701d-dc94-42be-b2e6-79221b18ee7d",
+ "attributes": {
+ "password": "lonely"
+ }
+ }
+}
+
+### Delete
+DELETE http://localhost:8080/json/school/f424701d-dc94-42be-b2e6-79221b18ee7d
diff --git a/src/test/resources/user.http b/src/test/resources/user.http
new file mode 100644
index 0000000..1f47abe
--- /dev/null
+++ b/src/test/resources/user.http
@@ -0,0 +1,45 @@
+### Query
+GET http://localhost:8080/json/user?sort=-username&page[number]=1&page[size]=10&filter[user]=username==lanyuan*
+Content-Type: application/vnd.api+json
+
+### Create
+POST http://localhost:8080/json/user
+Content-Type: application/vnd.api+json
+
+{
+ "data": {
+ "type": "user",
+ "attributes": {
+ "username": "tony",
+ "password": "tony"
+ }
+ }
+}
+
+### Modify
+PATCH http://localhost:8080/json/user/4a5668ef-52d7-4a46-a6f8-60d918f0562d
+Content-Type: application/vnd.api+json
+
+{
+ "data": {
+ "type": "user",
+ "id": "4a5668ef-52d7-4a46-a6f8-60d918f0562d",
+ "attributes": {
+ "password": "lonely"
+ }
+ }
+}
+
+### Modify Relationship
+PATCH http://localhost:8080/json/user/4a5668ef-52d7-4a46-a6f8-60d918f0562d/relationships/school
+Content-Type: application/vnd.api+json
+
+{
+ "data": {
+ "type": "school",
+ "id": "bd80714e-7345-4d65-97ae-3339c16b0275"
+ }
+}
+
+### Delete
+DELETE http://localhost:8080/json/user/f424701d-dc94-42be-b2e6-79221b18ee7d
diff --git a/test.http b/test.http
deleted file mode 100644
index 048e19d..0000000
--- a/test.http
+++ /dev/null
@@ -1,14 +0,0 @@
-### Query
-POST http://localhost:8080/get
-Content-Type: application/json
-Accept: application/json
-
-{
- "results[]": {
- "HostAssets": {
- "manufacturer": "华为"
- },
- "page": 0,
- "count": 2
- }
-}