JDAO — Java Persistence Framework[中文]

Introduction: JDAO is an innovative persistence layer solution designed to reduce coding efforts, increase productivity and performance, support multi-datasource integration, and enforce persistence layer programming standards. By leveraging JDAO, developers can decrease the amount of code required for the persistence layer by 30% to 50%, establish unified coding standards, minimize errors, and ensure easier maintenance and expansion.

JDAO’s structure is both simple and rigorous, with interfaces and function names that adhere to JDBC conventions, making the operations intuitive and self-explanatory. Even if you are new to JDAO, you can quickly understand its code and the associated data behaviors. The simplicity of JDAO ensures that you can master its usage within minutes.

Github
Jdao Dome
User Documentation

Key Features

  1. Code Generation: By running the JDAO code generation tool, standardized entity classes for database tables can be created, similar to Thrift/Protobuf.
  2. Efficient Serialization: The standardized entity classes implement efficient serialization and deserialization, achieving  3-12 times the performance of standard library methods, while the serialized data size is only 20% of that produced by standard methods.
  3. Support for Read-Write Separation: JDAO allows binding multiple data sources and supports data source binding at the table, class, and mapping interface levels, with built-in support for read-write separation.
  4. Data Caching: JDAO supports data caching with detailed control over cache data validity and recycling features.
  5. Wide Compatibility: Theoretically, JDAO supports all databases that implement the JDBC interface.
  6. Advanced Features: Includes support for transactions, stored procedures, batch processing, and other database operations.
  7. SQL file mapping: Similar to mybatis, support SQL and program separation

Addressing Hibernate and MyBatis Pain Points

Common Issues with Hibernate

  1. Over-encapsulation: Hibernate provides a high-level abstraction (including HQL) that helps developers focus on business logic rather than underlying SQL. While this advanced programming model reduces the need to understand SQL, it can obscure database behaviors, making performance bottlenecks hard to locate and optimize.
  2. Complexity: The steep configuration and learning curve can introduce unnecessary complexity in large projects, especially when fine-grained control is needed.
  3. Performance Issues: Reflection and proxy mechanisms can impact performance in high-concurrency scenarios, particularly during large-scale data processing.

Common Issues with MyBatis

  1. SQL Maintenance: MyBatis separates SQL from Java code using XML configuration files, enhancing flexibility and allowing direct SQL optimization. However, this can lead to an abundance of SQL configurations, increasing complexity and maintenance workload. In team environments, excessive SQL or XML files can cause version management and merge conflicts.
  2. Repetitive Work: MyBatis requires writing similar SQL statements and result mapping logic for each DAO. This repetitive work increases development time and error susceptibility, complicating code maintenance, especially for common CRUD operations.

JDAO’s Innovative Solutions

JDAO combines Hibernate’s abstraction and MyBatis’s flexibility to provide a powerful yet intuitive persistence layer solution.

  1. Standardized Mapping Entity Classes for Single Table CRUD Operations: Over 90% of database single-table operations can be performed using entity classes. These CRUD operations, typically not involving complex SQL optimization, can be generated by entity classes, reducing error rates and easing maintenance. JDAO’s caching and read-write separation mechanisms further optimize persistence layer efficiency. The data operation format of standardized entity classes is not just simple Java object function concatenation but more like objectified SQL operations, enhancing understandability.
  2. Execution of Complex SQL: Complex SQL, especially multi-table joins, often requires optimization, understanding table structures, indexes, and other database properties. Using Java objects to concatenate complex SQL can increase understanding difficulty and risk. JDAO recommends using its CRUD interfaces for complex SQL, providing flexible data conversion and efficient JavaBean mapping to avoid time-consuming reflection operations.
  3. Compatibility with MyBatis Mapping Files: For complex SQL operations, JDAO offers corresponding CRUD interfaces and supports XML-based SQL mapping similar to MyBatis. The difference is that MyBatis maps all SQL operations, while JDAO, despite offering full SQL mapping interfaces, suggests mapping only complex SQL or CRUD operations that standard entity classes cannot complete. JDAO’s SQL configuration files are inspired by MyBatis but feature a new parser for higher flexibility and parameter type tolerance.

Core Components

JDAO’s interface definitions and implementations closely align with standard JDBC interfaces, featuring intuitive naming conventions.

  1. Jdao: The main entry point, offering:
  2. JdaoCache: The cache entry point, supporting:
  3. JdaoSlave: The read-write separation entry point, supporting:
  4. JdaoMapper: Maps SQL to interfaces, supporting:


Quick Start

1. Installation

# Maven Installation
<dependency>
	<groupId>io.github.donnie4w</groupId>
	<artifactId>jdao</artifactId>
	<version>2.0.1</version>
	<scope>compile</scope>
</dependency>

2. Configure Data Source

Jdao.init(dataSource, DBType.MYSQL);
// dataSource: Data source instance
// Jdao.MYSQL: Database type

3. Generate Standardized Entity Classes

Use the JDAO code generation tool to create standardized entity classes for database tables.

4. Class Operations

// Data source configuration
Jdao.init(dataSource,DBType.MYSQL);

// select
Hstest t = new Hstest();
t.where(Hstest.ID.GT(1));
t.limit(20,10);
List<Hstest> list = t.selects(Hstest.Id);
for (Hstest hstest : list) {
	System.out.println(hstest);
}
// [SELECT SQL] select  id from hstest where id> ? limit ?,? [1,10,10] 

// update
Hstest t = new Hstest();
t.SetValue("hello world")
t.where(Hstest.ID.EQ(1));
t.update()
//[UPDATE SQL] update hstest set value=? where id=? ["hello world",1]

// delete
Hstest t = new Hstest();
t.where(Hstest.ID.EQ(1));
t.delete()
//[DELETE SQL]delete from hstest where id = ? [1]

// insert
Hstest hs = new Hstest();
hs.setRowname("hello world");
hs.setValue("123456789");
hs.insert();
//[INSERT SQL] insert to hstest (rowname,value) values(?,?) ["hello world","123456789"]

5. Jdao

CRUD Operations

// Query, return a single record
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=1", "hello");

//delete
int  i = Jdao.executeUpdate("delete from hstest where id = ?", 1);

6. JdaoCache

Configuration

// Bind Hstest.class to enable caching with a cache duration of 100 milliseconds
JdaoCache.bindClass(Hstest.class,new CacheHandle(100));
Hstest t = new Hstest();
t.where(Hstest.ID.EQ(3));
Hstest hs = t.select();
System.out.println(hs);
// Return cached data
Hstest t2 = new Hstest();
t2.where(Hstest.ID.EQ(3));
Hstest hs2 = t2.select();
System.out.println(hs2);

7. JdaoSlave

Read-Write Separation

JdaoSlave.bindClass(Hstest.class, DataSourceFactory.getDataSourceByPostgreSql(), DBType.POSTGRESQL);
// Primary database is MySQL, secondary database is PostgreSQL
Hstest t = new Hstest();
t.where(Hstest.ID.EQ(3));
Hstest hs = t.select();
System.out.println(hs);

8. JdaoMapper

Using XML to Map SQL

<mapper namespace="io.github.donnie4w.jdao.action.Mapperface">
    <select id="selectHstestById" parameterType="int" resultType="io.github.donnie4w.jdao.dao.Hstest">
        SELECT * FROM hstest  WHERE id < #{id} and age < #{age}
    </select>
</mapper>
// Initialize data source
Jdao.init(DataSourceFactory.getDataSourceBySqlite(), DBType.SQLITE);
// Read and parse XML configuration
JdaoMapper.build("mapper.xml");

JdaoMapper jdaoMapper = JdaoMapper.newInstance()
Hstest hs = jdaoMapper.selectOne("io.github.donnie4w.jdao.action.Mapperface.selectHstestById", 2, 26);

System.out.println(hs);

Java Interface Mapping for Mapper

public interface Mapperface {
    List<Hstest> selectAllHstest();
    List<Hstest> selectHstest(int id, int age);
    Hstest selectHstestByMap(Map map);
    List<Hstest> selectHstestByList(int id, int age);
    Hstest[] selectHstestByList(List list);
    Hstest selectHstestById(int id, int age);
    List<Hstest> selectHstestById(Integer id, Integer age);
    Hstest1 selectHstest1(int limit);
    List<Hstest1> selectHstest1(long limit);
    int insertHstest1(Hstest1 hs);
    int updateHstest1(Hstest1 hs);
    int deleteHstest1(Hstest1 hs);
}


@Test
public void selectMapperFace() throws JdaoException, JdaoClassException, SQLException {
    JdaoMapper jdaoMapper = JdaoMapper.newInstance();
    Mapperface mapper = jdaoMapper.getMapper(Mapperface.class);

    List<Hstest> list = mapper.selectHstestById(Integer.valueOf(5), Integer.valueOf(20));
    for (Hstest hs : list) {
        System.out.println(hs);
    }

    Hstest hstest = mapper.selectHstestById(5, 20);
    System.out.println(hstest);
}



Usage documentation interface of Jdao