-
Notifications
You must be signed in to change notification settings - Fork 19
Поддержка YDB в Jimmer ORM #215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
18a90e7
a892eb0
16df237
5346933
6e9da30
48013f7
c0c0d54
006155b
eaf4f10
88d30f9
495a77f
9658e1d
0c99f2d
268cd68
18d732f
a0a3c31
5fe2f13
61c4753
2df198c
a08ace7
7ee5bd1
d3094f9
db8d0fe
01a0685
7bd0a93
55da70c
5f6390e
c1ffb69
bf44f1b
d5d9491
9397554
48c456e
bd53d42
ba2c097
617cc75
b31d93d
3034bc2
828980c
8cd7ac2
23acf02
c28a608
3cf0e2e
085056b
d533c08
4c031b4
2e5fa29
e9ab0fc
167cd86
af0e0bb
7f34971
db5041b
3f5a61c
8a24874
08b7faa
f911c32
38aae75
135e09c
6e628d9
3201907
0906b61
8b53b91
6a4ebe7
96b357b
7c3cb45
29fd907
e30968a
4c19948
fd7c0a0
0decbca
1e8fcbb
dbeed53
9945da4
9cf674e
a67f8d9
d57b578
cb55a99
3f26a0e
83dc516
9db6a08
7b776a4
48be5b1
8434d6b
827cf67
ee19b1a
1433ac0
1589b13
38e6d0d
2c30093
e8c61e3
358b75d
7a87811
b3fbcc4
d9d8208
8911923
f658df2
c092fbb
c2b6ba7
bdd4ace
363670e
3e2bc16
1b4ab64
d60d31d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # YDB Dialect for Jimmer | ||
|
|
||
| ## Overview | ||
|
|
||
| This project contains a custom Jimmer dialect | ||
| for a simple integration between Jimmer ORM and Yandex Database (YDB). | ||
| For more thorough integration it is recommended to use the YqlClientBuilder class | ||
| for a custom JSqlClient. | ||
|
|
||
|
|
||
| ### Features | ||
|
|
||
| - Custom type mappings to utilize YDB's data types. | ||
| - Support for YDB-specific features and functions. | ||
| - Transaction modes and isolation levels. | ||
| - YDB keyset pagination. | ||
|
|
||
| ## Getting Started | ||
|
|
||
| ### Requirements | ||
|
|
||
| To use this Hibernate YDB Dialect, you'll need: | ||
|
|
||
| - Java 17 or above. | ||
| - Jimmer version 0.9.117 | ||
| - [YDB JDBC Driver](https://github.com/ydb-platform/ydb-jdbc-driver) | ||
| - Access to a YDB Database instance | ||
|
|
||
| ## Usage | ||
|
|
||
| ```java | ||
| DataSource dataSource = new DriverManagerDataSource("jdbc:ydb:grpc://localhost:2136/local"); | ||
| YqlClient yqlClient = getYqlClient(dataSource); | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 | ||
| http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
|
|
||
| <groupId>jimmer.ydb</groupId> | ||
| <artifactId>jimmer-ydb-dialect</artifactId> | ||
| <version>1.0-SNAPSHOT</version> | ||
| <name>YDB dialect for Jimmer ORM</name> | ||
|
|
||
| <properties> | ||
| <jimmer.version>0.9.117</jimmer.version> | ||
| <spring.version>7.0.2</spring.version> | ||
| <jmh.version>1.37</jmh.version> | ||
| <maven.compiler.release>17</maven.compiler.release> | ||
| </properties> | ||
|
|
||
| <dependencies> | ||
| <!-- https://mvnrepository.com/artifact/org.babyfish.jimmer/jimmer-sql --> | ||
| <dependency> | ||
| <groupId>org.babyfish.jimmer</groupId> | ||
| <artifactId>jimmer-sql</artifactId> | ||
| <version>${jimmer.version}</version> | ||
| </dependency> | ||
| <!-- Source: https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jsr310 --> | ||
| <dependency> | ||
| <groupId>com.fasterxml.jackson.datatype</groupId> | ||
| <artifactId>jackson-datatype-jsr310</artifactId> | ||
| <version>2.21.0</version> | ||
| <scope>compile</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.junit.jupiter</groupId> | ||
| <artifactId>junit-jupiter</artifactId> | ||
| <version>5.11.4</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <!-- https://mvnrepository.com/artifact/tech.ydb.jdbc/ydb-jdbc-driver --> | ||
| <dependency> | ||
| <groupId>tech.ydb.jdbc</groupId> | ||
| <artifactId>ydb-jdbc-driver</artifactId> | ||
| <version>2.3.20</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> | ||
| <dependency> | ||
| <groupId>org.springframework</groupId> | ||
| <artifactId>spring-jdbc</artifactId> | ||
| <version>${spring.version}</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <!-- Source: https://mvnrepository.com/artifact/org.slf4j/slf4j-api --> | ||
| <dependency> | ||
| <groupId>org.slf4j</groupId> | ||
| <artifactId>slf4j-api</artifactId> | ||
| <version>2.0.17</version> | ||
| <scope>compile</scope> | ||
| </dependency> | ||
| <!-- Source: https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j2-impl --> | ||
| <dependency> | ||
| <groupId>org.apache.logging.log4j</groupId> | ||
| <artifactId>log4j-slf4j2-impl</artifactId> | ||
| <version>2.25.3</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <!-- Source: https://mvnrepository.com/artifact/tech.ydb.test/ydb-junit5-support --> | ||
| <dependency> | ||
| <groupId>tech.ydb.test</groupId> | ||
| <artifactId>ydb-junit5-support</artifactId> | ||
| <version>2.3.29</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <!-- Source: https://mvnrepository.com/artifact/org.openjdk.jmh/jmh-core --> | ||
| <dependency> | ||
| <groupId>org.openjdk.jmh</groupId> | ||
| <artifactId>jmh-core</artifactId> | ||
| <version>${jmh.version}</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <!-- Source: https://mvnrepository.com/artifact/org.openjdk.jmh/jmh-generator-annprocess --> | ||
| <dependency> | ||
| <groupId>org.openjdk.jmh</groupId> | ||
| <artifactId>jmh-generator-annprocess</artifactId> | ||
| <version>${jmh.version}</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| </dependencies> | ||
|
|
||
| <build> | ||
| <plugins> | ||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-compiler-plugin</artifactId> | ||
| <version>3.10.1</version> | ||
| <configuration> | ||
| <annotationProcessorPaths> | ||
| <path> | ||
| <groupId>org.babyfish.jimmer</groupId> | ||
| <artifactId>jimmer-apt</artifactId> | ||
| <version>${jimmer.version}</version> | ||
| </path> | ||
| </annotationProcessorPaths> | ||
| <compilerArgs> | ||
| <arg>-parameters</arg> | ||
| </compilerArgs> | ||
| </configuration> | ||
| </plugin> | ||
| </plugins> | ||
| </build> | ||
| </project> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| package ydb.jimmer.dialect; | ||
|
|
||
| import com.fasterxml.jackson.core.JsonProcessingException; | ||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
| import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; | ||
| import org.babyfish.jimmer.jackson.ImmutableModule; | ||
| import org.babyfish.jimmer.meta.ImmutableProp; | ||
| import org.babyfish.jimmer.meta.ImmutableType; | ||
| import org.babyfish.jimmer.sql.cache.TransactionCacheOperator; | ||
| import org.babyfish.jimmer.sql.cache.UsedCache; | ||
| import org.babyfish.jimmer.sql.exception.ExecutionException; | ||
|
|
||
| import java.sql.PreparedStatement; | ||
| import java.sql.SQLException; | ||
| import java.util.Collection; | ||
| import java.util.Collections; | ||
| import java.util.UUID; | ||
|
|
||
| /** | ||
| * Uses UUID for the ids in the {@link #TABLE_NAME} SQL table. | ||
| */ | ||
| public class UuidTransactionCacheOperator extends TransactionCacheOperator { | ||
| public static final String TABLE_NAME = "JIMMER_TRANS_CACHE_OPERATOR"; | ||
|
|
||
| private static final String ID = "ID"; | ||
|
|
||
| private static final String IMMUTABLE_TYPE = "IMMUTABLE_TYPE"; | ||
|
|
||
| private static final String IMMUTABLE_PROP = "IMMUTABLE_PROP"; | ||
|
|
||
| private static final String CACHE_KEY = "CACHE_KEY"; | ||
|
|
||
| private static final String REASON = "REASON"; | ||
|
|
||
| private static final String INSERT_WITH_UUID = | ||
| "insert into " + | ||
| TABLE_NAME + "(" + | ||
| ID + | ||
| ", " + | ||
| IMMUTABLE_TYPE + | ||
| ", " + | ||
| IMMUTABLE_PROP + | ||
| ", " + | ||
| CACHE_KEY + | ||
| ", " + | ||
| REASON + | ||
| ") values(?, ?, ?, ?, ?)"; | ||
|
|
||
| private final ObjectMapper mapper; | ||
|
|
||
| private final int batchSize; | ||
|
|
||
| public UuidTransactionCacheOperator() { | ||
| this(null, 32); | ||
| } | ||
|
|
||
| public UuidTransactionCacheOperator(int batchSize) { | ||
| this(null, batchSize); | ||
| } | ||
|
|
||
| public UuidTransactionCacheOperator(ObjectMapper mapper) { | ||
| this(mapper, 32); | ||
| } | ||
|
|
||
| public UuidTransactionCacheOperator(ObjectMapper mapper, int batchSize) { | ||
| super(mapper, batchSize); | ||
|
|
||
| if (batchSize < 1) { | ||
| throw new IllegalArgumentException("`batchSize` cannot be less than 1"); | ||
| } | ||
| this.mapper = mapper != null ? | ||
| mapper : | ||
| new ObjectMapper() | ||
| .registerModule(new JavaTimeModule()) | ||
| .registerModule(new ImmutableModule()); | ||
| this.batchSize = batchSize; | ||
| } | ||
|
|
||
| @Override | ||
| public void delete(UsedCache<Object, ?> cache, Object key, Object reason) { | ||
| if (reason != null && !(reason instanceof String)) { | ||
| throw new IllegalArgumentException( | ||
| "The cache deletion reason can only be null or string when trigger type is `TRANSACTION_ONLY`" | ||
| ); | ||
| } | ||
| save(cache.type(), cache.prop(), Collections.singleton(key), (String) reason); | ||
| } | ||
|
|
||
| @Override | ||
| public void deleteAll(UsedCache<Object, ?> cache, Collection<Object> keys, Object reason) { | ||
| if (keys.isEmpty()) { | ||
| return; | ||
| } | ||
| if (reason != null && !(reason instanceof String)) { | ||
| throw new IllegalArgumentException( | ||
| "The cache deletion reason can only be null or string when trigger type is `TRANSACTION_ONLY`" | ||
| ); | ||
| } | ||
| save(cache.type(), cache.prop(), keys, (String) reason); | ||
| } | ||
|
|
||
| private void save( | ||
| ImmutableType type, | ||
| ImmutableProp prop, | ||
| Collection<Object> keys, | ||
| String reason | ||
| ) { | ||
| sqlClient().getConnectionManager().execute(con -> { | ||
| try { | ||
| try (PreparedStatement stmt = con.prepareStatement(INSERT_WITH_UUID)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Severity: Major The For a large collection of cache keys, this could cause memory pressure or exceed YDB's batch statement limits. Suggested fix: chunk the int count = 0;
for (Object key : keys) {
// ... setString calls ...
stmt.addBatch();
if (++count % batchSize == 0) {
stmt.executeBatch();
}
}
if (count % batchSize != 0) {
stmt.executeBatch();
}(where |
||
| int count = 0; | ||
| for (Object key : keys) { | ||
| stmt.setString(1, UUID.randomUUID().toString()); | ||
| stmt.setString(2, type != null ? type.toString() : null); | ||
| stmt.setString(3, prop != null ? prop.toString() : null); | ||
| stmt.setString(4, mapper.writeValueAsString(key)); | ||
| stmt.setString(5, reason); | ||
| stmt.addBatch(); | ||
|
|
||
| if (++count % batchSize == 0) { | ||
| stmt.executeBatch(); | ||
| } | ||
| } | ||
|
|
||
| if (count % batchSize != 0) { | ||
| stmt.executeBatch(); | ||
| } | ||
| } | ||
| } catch (SQLException | JsonProcessingException ex) { | ||
| throw new ExecutionException("Failed to save delayed cache deletion", ex); | ||
| } | ||
| return null; | ||
| }); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Severity: Minor
Confidence: Medium
liquibase-coreis declared atcompilescope but is not imported or used anywhere in the main source code (src/main/java). This adds a significant transitive dependency tree (~3 MB+) to the artifact for no functional benefit.If Liquibase is intended for future use, consider changing the scope to
providedortest. If it's not needed, remove it.