MyBatis - microfox-framework/MicroFox GitHub Wiki

πŸ—ƒοΈ MyBatis Integration

MicroFox integrates with MyBatis β€” a lightweight persistence framework that simplifies database interaction by mapping SQL queries to Java interfaces using annotations or XML.

πŸ“ Mapper Interfaces

Mappers in MyBatis are interfaces annotated with SQL commands. For example:

public interface ClientMapper {

    @Insert("INSERT INTO client (id, name, family) VALUES (#{id}, #{name}, #{family})")
    @SelectKey(statement = "SELECT client_seq.NEXTVAL FROM dual", keyProperty = "id", before = true, resultType = Long.class)
    void save(Client client);

    @Select("SELECT * FROM client")
    @Results({
        @Result(column = "id", property = "id"),
        @Result(column = "name", property = "name"),
        @Result(column = "family", property = "family"),
        @Result(property = "addresses", column = "id",
                many = @Many(select = "ir.moke.example.persistence.mapper.AddressMapper.findAddressByClientId"))
    })
    List<Client> findAll();

    @Select("SELECT * FROM client WHERE id=#{id}")
    @Results({
        @Result(column = "id", property = "id"),
        @Result(column = "name", property = "name"),
        @Result(column = "family", property = "family"),
        @Result(property = "addresses", column = "id",
                many = @Many(select = "ir.moke.example.persistence.mapper.AddressMapper.findAddressByClientId"))
    })
    Client findById(long id);
}

βš™οΈ MyBatis Configuration

The following setup initializes an H2 in-memory database using HikariCP as the connection pool, and registers mappers dynamically:

public class DB {

    public static void initializeMyBatis() {
        HikariConfig config = new HikariConfig();
        config.setDriverClassName(Driver.class.getCanonicalName());
        config.setJdbcUrl("jdbc:h2:mem:testdb;MODE=Oracle;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false");
        config.setUsername("sa");
        config.setPassword("sa");
        HikariDataSource dataSource = new HikariDataSource(config);

        Environment environment = new Environment("h2", new JdbcTransactionFactory(), dataSource);
        Configuration configuration = new Configuration(environment);
        configuration.setMapUnderscoreToCamelCase(true); // snake_case ↔ camelCase
        configuration.addMappers("ir.moke.example.persistence.mapper");

        MicroFoxMyBatis.configure(dataSource, configuration);
    }
}

πŸ§ͺ Running Example

Here’s how a job inserts and queries data using mybatis() utility:

public class MyBatisRunner {
    static {
        DB.initializeMyBatis();
        DB.initializeDatabase();
    }

    public static void main(String[] args) {
        Address a1 = new Address("Iran", "Tehran", "Tehran", "Enghelab", "0123456789");
        Address a2 = new Address("Iran", "Golestan", "Gorgan", "Azadi", "951753464");
        Client client = new Client("Mahdi", "Sheikh Hosseini", List.of(a1, a2));

        mybatis("h2", ClientMapper.class, mapper -> mapper.save(client));
        mybatis("h2", AddressMapper.class, mapper -> mapper.save(a1, client));
        mybatis("h2", AddressMapper.class, mapper -> mapper.save(a2, client));

        mybatis("h2", AddressMapper.class, mapper -> {
            mapper.findAll().forEach(addr -> System.out.println(JsonUtils.toJson(addr)));
        });
    }
}

πŸ” Dynamic SQL via SQL Builder

For more flexibility, Provider classes can return dynamic SQL using MyBatis's fluent SQL builder:

public class AddressProvider {
    public String insert(Map<String, Object> params) {
        Address address = (Address) params.get("address");
        Client client = (Client) params.get("client");
        return new SQL()
            .INSERT_INTO("address")
            .VALUES(MyBatisUtils.getColumns(Address.class) + ", client_id",
                    MyBatisUtils.getValues(address) + "," + client.getId())
            .toString();
    }
}

βœ… Features Used

  • Insert, @Select, @Results annotations
  • @SelectKey for database-generated IDs
  • Lazy-loading relations using @Many
  • Dynamic SQL generation using SQL builder
  • In-memory database setup using HikariCP + H2
  • Package-wide mapper registration

🧩 Future Plans (Optional Ideas)

  • Support for XML-based mappers alongside annotations
  • Integration with JPA-like annotations for mapping entity relations
  • Transactional unit-of-work abstraction
  • Multi-database support per tenant/schema
⚠️ **GitHub.com Fallback** ⚠️