Skip to content

Commit 9b5b292

Browse files
committed
add persistence module
1 parent 87f2057 commit 9b5b292

31 files changed

+810
-0
lines changed

pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@
220220
<module>springboot-starter-security-jwt</module>
221221
<module>springboot-starter-data-fast</module>
222222
<module>springboot-starter-id-generator</module>
223+
<module>springboot-starter-persistence</module>
223224
</modules>
224225
</profile>
225226

@@ -232,6 +233,7 @@
232233
<module>springboot-starter-security-jwt</module>
233234
<module>springboot-starter-data-fast</module>
234235
<module>springboot-starter-id-generator</module>
236+
<module>springboot-starter-persistence</module>
235237
</modules>
236238

237239
<build>
@@ -282,6 +284,7 @@
282284
<module>springboot-starter-security-jwt</module>
283285
<module>springboot-starter-data-fast</module>
284286
<module>springboot-starter-id-generator</module>
287+
<module>springboot-starter-persistence</module>
285288
</modules>
286289

287290

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="http://maven.apache.org/POM/4.0.0"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>springboot-parent</artifactId>
7+
<groupId>com.codingapi.springboot</groupId>
8+
<version>3.1.6</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>springboot-starter-persistence</artifactId>
13+
14+
<properties>
15+
<java.version>17</java.version>
16+
</properties>
17+
18+
<dependencies>
19+
20+
<dependency>
21+
<groupId>org.springframework.boot</groupId>
22+
<artifactId>spring-boot-starter-jdbc</artifactId>
23+
<scope>provided</scope>
24+
</dependency>
25+
26+
<dependency>
27+
<groupId>com.h2database</groupId>
28+
<artifactId>h2</artifactId>
29+
<scope>test</scope>
30+
</dependency>
31+
32+
</dependencies>
33+
34+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.codingapi.springboot.persistence;
2+
3+
import com.codingapi.springboot.persistence.scanner.SchemaScanner;
4+
import com.codingapi.springboot.persistence.schema.SchemaExecutor;
5+
import com.codingapi.springboot.persistence.schema.SchemaFactory;
6+
import org.springframework.beans.factory.annotation.Configurable;
7+
import org.springframework.context.annotation.Bean;
8+
9+
@Configurable
10+
public class AutoConfiguration {
11+
12+
@Bean
13+
public SchemaScanner domainScanner(SchemaExecutor schemaExecutor, SchemaFactory schemaFactory) {
14+
return new SchemaScanner(schemaExecutor, schemaFactory);
15+
}
16+
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.codingapi.springboot.persistence;
2+
3+
public interface DomainPersistence {
4+
5+
void save(Object domain);
6+
7+
<T> T get(Class<T> domainClass, Object id);
8+
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.codingapi.springboot.persistence.jdbc;
2+
3+
import com.codingapi.springboot.persistence.DomainPersistence;
4+
import com.codingapi.springboot.persistence.schema.SchemaExecutor;
5+
import com.codingapi.springboot.persistence.schema.SchemaFactory;
6+
import org.springframework.beans.factory.annotation.Configurable;
7+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
8+
import org.springframework.context.annotation.Bean;
9+
import org.springframework.jdbc.core.JdbcTemplate;
10+
11+
@ConditionalOnClass(JdbcTemplate.class)
12+
@Configurable
13+
public class JdbcAutoConfiguration {
14+
15+
@Bean
16+
public SchemaExecutor schemaExecutor(JdbcTemplate jdbcTemplate) {
17+
return new JdbcSchemaExecutor(jdbcTemplate);
18+
}
19+
20+
@Bean
21+
public DomainPersistence domainPersistence(JdbcTemplate jdbcTemplate) {
22+
return new JdbcDomainPersistence(jdbcTemplate);
23+
}
24+
25+
@Bean
26+
public SchemaFactory schemaFactory() {
27+
return new JdbcSchemaFactory();
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.codingapi.springboot.persistence.jdbc;
2+
3+
import com.codingapi.springboot.persistence.DomainPersistence;
4+
import com.codingapi.springboot.persistence.scanner.SchemaContext;
5+
import com.codingapi.springboot.persistence.schema.SaveSchema;
6+
import com.codingapi.springboot.persistence.schema.Schema;
7+
import com.codingapi.springboot.persistence.schema.SearchSchema;
8+
import lombok.AllArgsConstructor;
9+
import org.springframework.dao.EmptyResultDataAccessException;
10+
import org.springframework.jdbc.core.BeanPropertyRowMapper;
11+
import org.springframework.jdbc.core.JdbcTemplate;
12+
import org.springframework.jdbc.support.GeneratedKeyHolder;
13+
import org.springframework.jdbc.support.KeyHolder;
14+
15+
import java.sql.PreparedStatement;
16+
import java.sql.Statement;
17+
18+
@AllArgsConstructor
19+
public class JdbcDomainPersistence implements DomainPersistence {
20+
21+
private final JdbcTemplate jdbcTemplate;
22+
23+
@Override
24+
public void save(Object domain) {
25+
Schema schema = SchemaContext.getINSTANCE().getSchema(domain.getClass());
26+
if (schema != null) {
27+
SaveSchema saveSchema = schema.insertSchema();
28+
if (schema.getSchemaProperty().hasIdValue(domain)) {
29+
jdbcTemplate.update(saveSchema.saveSchema(), saveSchema.getSaveValues(domain));
30+
} else {
31+
KeyHolder keyHolder = new GeneratedKeyHolder();
32+
jdbcTemplate.update(con -> {
33+
PreparedStatement ps = con.prepareStatement(saveSchema.saveSchema(false), Statement.RETURN_GENERATED_KEYS);
34+
int index = 1;
35+
for (Object value : saveSchema.getSaveValues(domain, false)) {
36+
ps.setObject(index++, value);
37+
}
38+
return ps;
39+
}, keyHolder);
40+
schema.getSchemaProperty().setIdValue(domain, keyHolder.getKey());
41+
}
42+
}
43+
}
44+
45+
@Override
46+
public <T> T get(Class<T> domainClass, Object id) {
47+
Schema schema = SchemaContext.getINSTANCE().getSchema(domainClass);
48+
if (schema != null) {
49+
SearchSchema searchSchema = schema.getById();
50+
String sql = searchSchema.getById();
51+
try {
52+
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new BeanPropertyRowMapper<>(domainClass));
53+
} catch (EmptyResultDataAccessException e) {
54+
// Handle the case where no results are found or rethrow a custom exception
55+
return null;
56+
}
57+
}
58+
return null;
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.codingapi.springboot.persistence.jdbc;
2+
3+
import com.codingapi.springboot.persistence.schema.Schema;
4+
import com.codingapi.springboot.persistence.schema.SchemaExecutor;
5+
import lombok.AllArgsConstructor;
6+
import org.springframework.jdbc.core.JdbcTemplate;
7+
import org.springframework.stereotype.Repository;
8+
9+
@Repository
10+
@AllArgsConstructor
11+
public class JdbcSchemaExecutor implements SchemaExecutor {
12+
13+
private final JdbcTemplate jdbcTemplate;
14+
15+
16+
@Override
17+
public void create(Schema schema) {
18+
jdbcTemplate.execute(schema.buildSchema().createSchema());
19+
}
20+
21+
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.codingapi.springboot.persistence.jdbc;
2+
3+
import com.codingapi.springboot.persistence.jdbc.schema.JdbcSchema;
4+
import com.codingapi.springboot.persistence.schema.Schema;
5+
import com.codingapi.springboot.persistence.schema.SchemaFactory;
6+
7+
public class JdbcSchemaFactory implements SchemaFactory {
8+
9+
@Override
10+
public Schema getSchema(Class<?> domainClass) {
11+
return new JdbcSchema(domainClass);
12+
}
13+
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.codingapi.springboot.persistence.jdbc.schema;
2+
3+
import com.codingapi.springboot.persistence.schema.BuildSchema;
4+
import com.codingapi.springboot.persistence.schema.Property;
5+
import com.codingapi.springboot.persistence.schema.Schema;
6+
7+
import java.util.List;
8+
9+
public class JdbcBuildSchema extends BuildSchema {
10+
11+
public JdbcBuildSchema(Schema schema) {
12+
super(schema);
13+
}
14+
15+
@Override
16+
public String createSchema() {
17+
StringBuilder sql = new StringBuilder();
18+
sql.append("CREATE TABLE IF NOT EXISTS ");
19+
sql.append(property.getSchemaName());
20+
sql.append(" (");
21+
sql.append("id INT PRIMARY KEY AUTO_INCREMENT,");
22+
List<Property> properties = property.getProperties(false);
23+
for (int i = 0; i < properties.size(); i++) {
24+
Property property = properties.get(i);
25+
sql.append(property.getName());
26+
sql.append(" ");
27+
sql.append(property.getJdbcType());
28+
if (i != properties.size() - 1) {
29+
sql.append(", ");
30+
}
31+
}
32+
sql.append(")");
33+
return sql.toString();
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.codingapi.springboot.persistence.jdbc.schema;
2+
3+
import com.codingapi.springboot.persistence.schema.Property;
4+
import com.codingapi.springboot.persistence.schema.SaveSchema;
5+
import com.codingapi.springboot.persistence.schema.Schema;
6+
7+
public class JdbcSaveSchema extends SaveSchema {
8+
9+
public JdbcSaveSchema(Schema schema) {
10+
super(schema);
11+
}
12+
13+
@Override
14+
public String saveSchema(boolean hasId) {
15+
StringBuilder sql = new StringBuilder();
16+
sql.append("INSERT INTO ");
17+
sql.append(property.getSchemaName());
18+
sql.append(" (");
19+
for (Property property : property.getProperties(hasId)) {
20+
sql.append(property.getName());
21+
sql.append(", ");
22+
}
23+
sql.delete(sql.length() - 2, sql.length());
24+
sql.append(") VALUES (");
25+
for (Property property : property.getProperties(hasId)) {
26+
sql.append("?, ");
27+
}
28+
sql.delete(sql.length() - 2, sql.length());
29+
sql.append(")");
30+
return sql.toString();
31+
}
32+
33+
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.codingapi.springboot.persistence.jdbc.schema;
2+
3+
import com.codingapi.springboot.persistence.schema.BuildSchema;
4+
import com.codingapi.springboot.persistence.schema.SaveSchema;
5+
import com.codingapi.springboot.persistence.schema.Schema;
6+
import com.codingapi.springboot.persistence.schema.SearchSchema;
7+
8+
public class JdbcSchema extends Schema {
9+
10+
public JdbcSchema(Class<?> domainClass) {
11+
super(domainClass);
12+
}
13+
14+
@Override
15+
public BuildSchema buildSchema() {
16+
return new JdbcBuildSchema(this);
17+
}
18+
19+
@Override
20+
public SaveSchema insertSchema() {
21+
return new JdbcSaveSchema(this);
22+
}
23+
24+
@Override
25+
public SearchSchema getById() {
26+
return new JdbcSearchSchema(this);
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.codingapi.springboot.persistence.jdbc.schema;
2+
3+
import com.codingapi.springboot.persistence.schema.Schema;
4+
import com.codingapi.springboot.persistence.schema.SearchSchema;
5+
6+
public class JdbcSearchSchema extends SearchSchema {
7+
8+
public JdbcSearchSchema(Schema schema) {
9+
super(schema);
10+
}
11+
12+
@Override
13+
public String getById() {
14+
return "SELECT * FROM " + property.getSchemaName() + " WHERE id = ?";
15+
}
16+
17+
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.codingapi.springboot.persistence.register;
2+
3+
import lombok.Getter;
4+
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
8+
@Getter
9+
public class DomainClassRegister {
10+
11+
private final List<Class<?>> classes;
12+
13+
public final static DomainClassRegister INSTANCE = new DomainClassRegister();
14+
15+
private DomainClassRegister() {
16+
this.classes = new ArrayList<>();
17+
}
18+
19+
public void register(Class<?> domainClass) {
20+
this.classes.add(domainClass);
21+
}
22+
23+
public boolean supports(Class<?> domainClass) {
24+
return this.classes.stream()
25+
.anyMatch(clazz -> clazz.equals(domainClass));
26+
27+
}
28+
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.codingapi.springboot.persistence.scanner;
2+
3+
import com.codingapi.springboot.persistence.schema.Schema;
4+
import lombok.Getter;
5+
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
9+
public class SchemaContext {
10+
11+
@Getter
12+
public final static SchemaContext INSTANCE = new SchemaContext();
13+
14+
private final List<Schema> schemas;
15+
16+
private SchemaContext() {
17+
this.schemas = new ArrayList<>();
18+
}
19+
20+
public void register(Schema schema) {
21+
this.schemas.add(schema);
22+
}
23+
24+
public Schema getSchema(Class<?> domainClass) {
25+
return schemas.stream()
26+
.filter(schema -> schema.getDomainClass().equals(domainClass))
27+
.findFirst()
28+
.orElseThrow(() -> new RuntimeException("schema not found"));
29+
}
30+
}

0 commit comments

Comments
 (0)