J-Framework Data
Data API makes the development of database-driven applications in Java more convenient and efficient.
Dependency
Most likely, you will NOT need to add the direct dependency of this project, since it’s already included in the parent projects or the other framework projects. However, if you need to, the dependency is as follows.
<!-- https://mvnrepository.com/artifact/com.jalalkiswani/j-framework-core -->
<dependency>
<groupId>com.jalalkiswani</groupId>
<artifactId>j-framework-data</artifactId>
<version>7.0.0-SNAPSHOT</version>
</dependency>
Main Features
-
Elegant and easy-to-use API (proven to work with minimum Java experience)
-
Enables the best of the following in the same App:
-
JDBC (SQL inside Java),
-
JPA ((Java classes with mapping to database without SQL code)
-
NoSQL (JSON and document-based database such as MongoDB)
-
-
Unified configuration file for JDBC, JPA, and NoSQL, no need for
pirsistence.xml
or any other files. -
Built-in connection pooling with intensive optimization configurations.
-
Multi-database support
-
Intensive Logging,
-
Built in Audit-Trail.
-
Built in caching mechanism.
-
Efficient Timing for queries with near-zero overhead.
-
Provide connections with the needed client information for debugging and monitoring purposes.
-
Dynamic Data Access API.
-
Auto database synchronization based on JPA entities (thanks to Hibernate)
-
Enable having SQL queries inside SQL files, which is more convenient and easily maintainable by database developers.
-
Sophisticated support for stored procedures and custom database objects
Basic Usage
JDBC
For JDBC data access, create JKDataAccessService
as follows, then enjoy calling SQL statements on
database with which could be the most convenient JDBC approach for people coming from Oracle and Database programming
background.
JKDataAccessService jdbc = JKDataAccessFactory.getDataAccessService();
JPA
For JPA and ORM Mapping, place your JPA entities in the com.app.entities
package, then create
JKObjectDataAccess
as follows, that’s it, now you have a wonderful set of methods to be used for
your database-driven applications.
JKObjectDataAccess orm = JKDataAccessFactory.getObjectDataAccessService();
You can always change the default package names of the entities using the db-entities-packages
property in the config file src/main/resources/config.properties
.
Even if you would like to use JDBC in your code, I always prefer to build JPA entities
to create the database structure on the |
Configurations
The framework creates a local file-based H2 database by default, so basically, no configuration is needed.
This could be a good idea for testing automation, proof-of-concepts, or trying things out. However, for real-life applications, you will need to go with production-grade database engines.
To manage the configuration of your database(s), please refer to the Config Guide.
Naming Strategy
By default, the framework will map to database tables according to the following rules:
-
Convert the camel-case names to snake-case (underscores).
-
Lowercase the names.
In the case of Oracle:
-
All the names will be converted to uppercase
-
Any field with a reserved keyword name will be post-fixed with an underscore, for example: a field with a
UID
name will be mapped to a column with the nameUID_
Default Configuration
Below are the default configurations, which are set in the default.config.properties in the framework
#H2 Configurations
#hibernate.connection.driver_class = org.h2.Driver
#hibernate.connection.url = jdbc:h2:file:~/.jk/h2-db/h2db2.data
#hibernate.dialect = org.hibernate.dialect.H2Dialect
#MySQl Config
#hibernate.connection.driver_class = com.mysql.jdbc.Driver
#hibernate.connection.url = jdbc:mysql://localhost:3306/app?createDatabaseIfNotExist=true
#hibernate.dialect = org.hibernate.dialect.MySQL57Dialect
#hibernate.connection.username = root
#hibernate.connection.password = 123456
#Oracle Config, you will need to add oracle driver dependency,
#checkout, option 4(System Path): https://www.mkyong.com/maven/how-to-add-oracle-jdbc-driver-in-your-maven-local-repository/
#hibernate.connection.driver_class = oracle.jdbc.driver.OracleDriver
#hibernate.connection.url = jdbc:oracle:thin:@localhost:1521/orclpdb1
#hibernate.dialect = org.hibernate.dialect.Oracle10gDialect
#hibernate.c3p0.preferredTestQuery=SELECT 1 FROM DUAL
#hibernate.connection.username = sa
#hibernate.connection.password = sa
#To build database structure from Entities
#hibernate.hbm2ddl.auto=update
#Package to scan for JPA entities, CSV value is allowed for multiple packages
#db-entities-packages=com.app,
nosql.url=mongodb://localhost:27017/
nosql.db.name=app
nosql.db.user=
nosql.db.password=
hibernate.connection.url = jdbc:h2:file:~/.jk/h2-db/h2db2.data;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE;DATABASE_TO_UPPER=FALSE;
hibernate.connection.username = sa
hibernate.connection.password = sa
#hibernate.c3p0.initialPoolSize=1
hibernate.c3p0.min_size=1
hibernate.c3p0.max_size=100
#important to to avoid AUTO id error in JPA: https://stackoverflow.com/questions/49813666/table-dbname-hibernate-sequence-doesnt-exist
hibernate.id.new_generator_mappings=false
#hibernate.physical_naming_strategy: already calculated internally
#this will ensure escaping all fields that are keywords
hibernate.globally_quoted_identifiers=true
#hibernate.use_sql_comments=false
hibernate.format_sql=true
hibernate.show_sql=false
hibernate.hbm2ddl.auto=update
#hot deployment
hibernate.c3p0.privilegeSpawnedThreads=true
hibernate.c3p0.contextClassLoaderSource=library
#connections cleanup
#seconds, connections stay un-used for n seconds
hibernate.c3p0.timeout=3600
hibernate.c3p0.unreturnedConnectionTimeout=3600
#millis, this time could be needed in the init phase of the pool, need verification
hibernate.c3p0.checkoutTimeout=20000
hibernate.c3p0.testConnectionOnCheckout=true
#refresh the connection anyways after this timeout
#hibernate.c3p0.maxConnectionAge=18000
hibernate.c3p0.debugUnreturnedConnectionStackTraces=true
#millis-seconds
hibernate.c3p0.acquire_increment=1
hibernate.c3p0.acquireRetryDelay=10000
hibernate.c3p0.acquireRetryAttempts=1
hibernate.c3p0.idleConnectionTestPeriod=30
hibernate.c3p0.maxStatements=1000
hibernate.c3p0.maxStatementsPerConnection=100
hibernate.c3p0.numHelperThreads=10
#hibernate.c3p0.maxAdministrativeTaskTime=100
#hibernate.c3p0.automaticTestTable=
#hibernate,c3p0,plain,dbcp
jk.data.datasource.impl=hibernate
hibernate.connection.autocommit=true
Git DataAccess
JKGitWrapper is a full wrapper that enables full communication with a Git repository.
A full example can be found below.
String url = "Remote Repository URL";
String userName = "UserName";
String password = "Password";
String localPath = "local-source-path";
JKGitWrapper gw = new JKGitWrapper();
gw.url(url).user(userName).password(password).localPath(localPath);
Git git = gw.cloneRepo();
JKIOUtil.createDirectory(gw.getLocalPath(), "dir1");
JKIOUtil.createDirectory(gw.getLocalPath(), "dir2");
JKIOUtil.createDirectory(gw.getLocalPath(), "dir2/dir2-1");
JKIOUtil.createDirectory(gw.getLocalPath(), "dir3");
JKIOUtil.writeDataToFile("Hello from uncle Jalal0", new File(gw.getLocalPath(), "dir1/test.txt"));
JKIOUtil.writeDataToFile("Hello from uncle Jalal1", new File(gw.getLocalPath(), "dir2/test.txt"));
JKIOUtil.writeDataToFile("Hello from uncle Jalal2", new File(gw.getLocalPath(), "dir2/dir2-1/test.txt"));
JKIOUtil.writeDataToFile("Hello from uncle Jalal3", new File(gw.getLocalPath(), "dir3/test.txt"));
gw.add(git);
gw.commit(git);
gw.push(git);
Multi-Database Support
In the config file, you can add a prefix to the same configuration used in normal database setup.
mydb.hibernate.connection.url =jdbc:oracle:thin:@0.0.0.0:1521:DB mydb.hibernate.connection.username =user mydb.hibernate.connection.password = pass
Then, in your DataAccess
class, create an instance of the JKDataAccessService
with the prefix:
JKDataAccessService service=JKDataAccessFactory.getDataAccessService("mydb);
To unify the database prefix in one place, it is recommended to create a DataAccess super class
that extends one of the |