JDAO —— Java Persistence Framework [中文]
JDAO is an innovative persistence layer solution designed to reduce programming workload, enhance productivity, improve performance, support integration of multiple data sources, enable read-write separation, and establish standards for persistence layer programming. By leveraging JDAO in your persistence layer design, you can reduce coding by up to 30%, sometimes even 50% or more, while establishing a unified programming standard that reduces errors and facilitates maintenance and expansion.
The mapping module of Jdao realizes the separation of SQL and program, and the mapping module has the same core function as myBatis. In addition to mybatis and ORMs based on the myBatis family, it is the only orm framework that implements this feature.
- Lightweight: JDAO has no dependencies. All features are implemented within JDAO itself, ensuring it integrates smoothly into various projects without being affected by updates or changes in other projects.
- Efficiency: One of the main goals of JDAO is efficiency, avoiding unnecessary overhead. Its performance is very close to direct JDBC calls, with minimal performance loss due to ORM encapsulation.
- Flexibility: JDAO supports rich dynamic SQL construction capabilities, including native dynamic SQL, mapping dynamic SQL, and entity class dynamic SQL.
- Security: JDAO eliminates the risk of SQL injection. It offers similar mapping functionality to MyBatis but removes potential security vulnerabilities.
- Comprehensive: Combining the abstraction of Hibernate and the flexibility of MyBatis, JDAO provides a standardized and efficient ORM application solution.
- Code Generation: Run the JDAO code generation tool to create standardized entity classes for database tables, similar to Thrift/Protocol Buffers.
- Efficient Serialization: The standardized entity classes for tables implement efficient serialization and deserialization, which is 3-12 times faster than standard library serialization methods and has a serialized size about 20% of the standard method.
- Read-Write Separation: JDAO supports binding multiple data sources and supports data source binding to tables, classes, mapping interfaces, etc., as well as read-write separation.
- Data Caching: JDAO supports data caching and allows detailed control over cache expiration and data eviction.
- Wide Compatibility: JDAO theoretically supports all databases that implement the JDBC interface.
- Advanced Features: Supports transactions, stored procedures, batch processing, and other database operations.
- Dynamic SQL: JDAO implements rich dynamic SQL construction capabilities. It supports dynamic SQL tag mapping construction and native SQL dynamic construction.
- MyBatis Compatibility: In the mapping module, JDAO uses MyBatis tag definitions and implements the same functional characteristics.
- Over-Abstraction: While Hibernate's high-level abstraction (including HQL) helps developers focus on business logic rather than underlying SQL, this abstraction can mask the specific behaviors of the underlying database, leading to performance bottlenecks that are hard to identify and optimize.
- Complexity: The configuration and learning curve are steep, which may introduce unnecessary complexity for large projects, especially when fine-grained control is required.
- Performance Issues: Reflection and proxy mechanisms can affect performance in high-concurrency scenarios, particularly during large-scale data processing.
- SQL Maintenance: MyBatis separates SQL from Java code using XML configuration files, increasing flexibility and allowing direct writing and optimization of SQL. However, this can lead to a large number of SQL configurations, increasing complexity and maintenance workloads.
- Redundant Work: Each DAO in MyBatis requires writing similar SQL statements and result mapping logic, which not only increases development time but also introduces errors and increases the complexity of code maintenance.
- Complete Table Object Mapping for Single Table CRUD Operations: Mapping all operations to table objects is a classic approach used by Hibernate, which can lead to over-encapsulation issues. JDAO supports auto-generating mapping entity classes dedicated to CRUD operations on single tables. Its underlying dynamic SQL construction effectively addresses the problem of generating a large amount of similar SQL for similar table operations.
- Complete SQL Mapping Objects for Complex SQL Operations: In practice, complex SQL, especially multi-table joins, often require optimization, which necessitates a good understanding of table structures, index properties, and other database attributes. Concatenating complex SQL strings using Java objects typically increases the difficulty of comprehension. Sometimes, developers might not even know what the final SQL statement looks like after concatenation, which undoubtedly increases risk and maintenance difficulty. JDAO implements the core feature of MyBatis — the SQL mapping capability, allowing the definition of SQL in XML configuration files and mapping it to Java objects or interfaces.
SqlBuilder
for Native SQL Dynamic Construction: JDAO supports dynamic construction of native SQL. For extremely complex SQL, including database advanced features such as functions or stored procedures, JDAO supports dynamic construction usingSqlBuilder
. This is a procedural implementation of dynamic tags, based on Java programs to construct dynamic SQL, enabling the creation of any form of SQL.
-
JDAO is positioned as a flexible and extensible foundational framework. Similar to Hibernate and MyBatis, its functionalities primarily correspond to basic CRUD operations on databases.
-
Differences Between JDAO and MyBatis-Plus Type Frameworks:
- Frameworks like MyBatis-Plus are extension frameworks, typically designed with a plethora of advanced features built-in to meet the needs of higher productivity and faster development. While this is convenient for agile development requirements, the added features are not necessary for all projects. Especially for applications with mature architectures and complex business logic, there might be a preference for controlling every detail.
- JDAO is a foundational framework that does not come with a surplus of advanced features, maintaining good extensibility. Like Hibernate and MyBatis, its design aims to solve data access problems across different scenarios. However, both complete table mapping and complete SQL mapping have their issues; JDAO provides various object encapsulation strategies to address persistence layer solutions for both small and large scenarios.
-
The foundational positioning and clean interfaces of JDAO make it suitable for both small and large projects, as well as for small and large teams.
<!-- Using Maven -->
<dependency>
<groupId>io.github.donnie4w</groupId>
<artifactId>jdao</artifactId>
<version>2.1.0</version>
</dependency>
static {
Jdao.init(DataSourceFactory.getDataSourceBySqlite(), DBType.SQLITE); // Initialize data source, first parameter is DataSource, second parameter is database type
Jdao.setLogger(true); // Enable logging in the test environment to output executed SQL and parameters
}
Hstest t = new Hstest();
t.where(Hstest.ID.GT(1));
t.limit(20, 10);
Hstest rs = t.select(); // Query
Hstest t = new Hstest();
t.setValue("hello world");
t.where(Hstest.ID.EQ(1));
t.update(); // Update
Hstest t = new Hstest();
t.where(Hstest.ID.EQ(1));
t.delete(); // Delete
Hstest hs = new Hstest();
hs.setRowname("hello world");
hs.setValue("123456789");
hs.insert(); // Insert
// Query
Hstest hs = Jdao.executeQuery(Hstest.class, "select * from Hstest order by id desc limit ?", 1);
System.out.println(hs);
// Insert
int i = Jdao.executeUpdate("insert into hstest2(rowname, value) values(?, ?)", "helloWorld", "123456789");
// Update
int i = Jdao.executeUpdate("update hstest set value=? where id=?", "hello", 1);
// Delete
int i = Jdao.executeUpdate("delete from hstest where id=?", 1);
// Bind Hstest.class to enable caching
JdaoCache.bindClass(Hstest.class);
// Read-Write Separation Binding
JdaoSlave.bindClass(Hstest.class, DataSourceFactory.getDataSourceByPostgreSql(), DBType.POSTGRESQL);
<select id="selectHstestById" resultType="io.github.donnie4w.jdao.dao.Hstest">
SELECT * FROM hstest WHERE id < #{id} and age < #{age}
</select>
@Test
public void selectOne() throws JdaoException, JdaoClassException, SQLException {
Hstest hs = jdaoMapper.selectOne("io.github.donnie4w.jdao.action.Mapperface.selectHstestById", 2, 26);
System.out.println(hs);
}
<select id="demo1" resultType="io.github.donnie4w.jdao.dao.Hstest">
SELECT * FROM hstest
<where>
<if test="rowname!= 'hello'">
and rowname = #{rowname}
</if>
<if test="id >0">
AND id = #{id}
</if>
</where>
</select>
@Test
public void demo1() throws JdaoException, JdaoClassException, SQLException {
Hstest hs = new Hstest();
hs.setId(31);
hs.setRowname("hello");
List<Hstest> listSlave = jdaoMapper.selectList("io.github.donnie4w.jdao.action.Dynamic.demo1", hs);
for (Hstest hstest : listSlave) {
System.out.println(hstest);
}
}
@Test
public void testAppendIf() throws JdaoException, SQLException {
Map<String, Object> context = new HashMap<>();
context.put("id", 31);
SqlBuilder builder = new SqlBuilder();
builder.append("SELECT * FROM HSTEST where 1=1")
.appendIf("id>0", context, "and id=?", context.get("id"))
.append("ORDER BY id ASC");
List<DataBean> list = builder.selectList();
for (DataBean bean : list) {
System.out.println(bean);
}
}