Hope it will bring you the programming experiences: coding with SQL/DB is just like coding with Collections.
-
PreparedQuery, NamedQuery, PreparedCallableQuery, Dao/CrudDao/JoinEntityHelper, Jdbc, JdbcUtil, JdbcUtils, DataSet, ConditionFactory(CF), SQLBuilder, DynamicSQLBuilder...
-
Looking for: SQLExecutor and Mapper? Please refer to branch: sql_executor_mapper
Abacus-jdbc provides the best APIs, which you won't find in other libraries, for preparing query/setting parameters/extracting result. A lot of DB operations can be done through Dao/CrudDao without writing a single data access method.
- Work with sql statements
String query = "SELECT first_name, last_name FROM account WHERE first_Name = ?";
Optional<Account> account = JdbcUtil.prepareQuery(query)
.setString(1, "Tom") // setInt/setString/setDate/...
// OR .setParameters(entity/map) for named query.
// OR .setParameters(stmt -> {}) by functional interface.
.findFirst(Account.class); // findOnlyOne(Account.class/RowMapper)/list/...
// OR ./query(ResultExtractor).../queryForInt/String/...
// Or .stream(Account.class/RowMapper).filter/map/collect/...
// More query/update/delete/batchInsert/batchUpdate...
- Work with Dao:
public interface UserDao extends JdbcUtil.CrudDao<User, Long, SQLBuilder.PSC, UserDao> {
// ...
@NamedInsert("INSERT INTO user (id, first_name, last_name, email) VALUES (:id, :firstName, :lastName, :email)")
void insertWithId(User user) throws SQLException;
}
User user = User.builder().id(100).firstName("Forrest").lastName("Gump").email("123@email.com").build();
userDao.insertWithId(user);
User userFromDB = userDao.gett(100L);
System.out.println(userFromDB);
userDao.stream(CF.eq("firstName", "Forrest")).filter(it -> it.getLastName().equals("Gump"));
userDao.deleteById(100L);
- How to write/generate sql scripts:
String query = "select first_name, last_name from account where id = ?"; // write by yourself.
String query = PSC.select("firstName, "lastName").from(Account.class).where(CF.eq("id")).sql(); // use SQLBuilder
// To select all fields:
String query = PSC.selectFrom(Account.class).where(CF.eq("id")).sql();
- Where to put sql scripts:
// define it as constant or local variable
static final String query = "select ....";
String query = "select ....";
// annotated on method in Dao interface
@NamedUpdate("UPDATE user SET first_name = :firstName, last_name = :lastName WHERE id = :id")
int updateFirstAndLastName(@Bind("firstName") String newFirstName, @Bind("lastName") String newLastName, @Bind("id") long id) throws SQLException;
// Or define it in nested class and then annotated by field name
public interface UserDao extends JdbcUtil.CrudDao<User, Long, SQLBuilder.PSC, UserDao>, JdbcUtil.JoinEntityHelper<User, SQLBuilder.PSC, UserDao> {
...
@Select(id = "sql_listToSet")
Set<User> listToSet(int id) throws SQLException;
static final class SqlTable {
@SqlField
static final String sql_listToSet = PSC.selectFrom(User.class).where(CF.gt("id")).sql();
}
}
// Or define it in xml file and then annotated by id. Refer to : ./schema/SQLMapper.xsd
<sqlMapper>
<sql id="sql_listToSet", fetchSize = 10>select first_name, last_name from user where id = ?</sql>
</sqlMapper>
static final UserDao userDao = JdbcUtil.createDao(UserDao.class, dataSource, sqlMapper);
// Here I would suggest putting the sql scripts in the closest place where it will be executed.
- How to execute sql scripts:
String query = "select first_name, last_name from account where id = ?";
1) By Prepared query.
JdbcUtil.prepareQuery(query).setLong(1, id).findOnlyOne(Account.class); // or .findFirst/list/stream...
2) By Dao method
@Select("select first_name, last_name from account where id = ?")
Optional<Account> selectNameById(int id) throws SQLException;
accountDao.selectNameById(id);
- How about dynamic sql scripts:
// Dao interfaces provides tens of methods for most used daily query.
accountDao.get(id, N.asList("firstName", "lastName"));
accountDao.deleteById(id);
...
// you can also use SQLBuilder and DynamicSQLBuilder to composite sql scripts.
- How to set parameters by Entity or map:
// By default, the built-in methods in Dao interfaces already support entity/Map parameters.
accountDao.update(account);
accountDao.update(updatePropMap, id);
...
// Use NamedQurey
String sql = NSC.update(Account.class).set(N.asList("firstName, "lastName")).where(CF.eq("id")).sql();
JdbcUtil.prepareNamedQuery(sql).setParameters(account).update();
- What's the best way to extract query result:
// To extract single result(single column)
JdbcUtil.prepareQuery(sql).setParameters(...).queryForInt/Long/String/SingleResult/...
// To extract one row.
JdbcUtil.prepareQuery(sql).setParameters(...).findFirst/firstOnlyOne(targetEntityClass/rowMapper/biRowMapper...);
// To list/stream
JdbcUtil.prepareQuery(sql).setParameters(...).list/stream(targetEntityClass/rowMapper/biRowMapper...);
// general query by DataSet
JdbcUtil.prepareQuery(sql).setParameters(...).query();
// Merge result.
String sql = "select user.id, first_name, last_name, device.id \"devices.id\", device.model \"devices.model\" from user left join device on user.id = device.user_id;
List<User> userWithDevices = JdbcUtil.prepareQuery(sql).setParameters(...).query().toMergedEntities(User.class);
@Data
public class User {
private int id;
private String firstName;
private String lastName;
List<Device> devices;
}
@Data
public class Device {
private int id;
private String model;
}
- More samples/questions? take a look at the samples ./samples/com.landawn.abacus.samples/...
Download/Installation & Changes:
-
Gradle:
// JDK 1.8 or above:
compile 'com.landawn:abacus-jdbc:3.3.1'
- Introduction to JDBC
- Programming in JDBC/DB with JdbcUtil/PreparedQuery/SQLExecutor/Mapper/Dao.
- More samples
Also See: abacus-common, abacus-entity-manager.
lombok, Jinq, jdbi, Mybatis, Sharding-JDBC, mapstruct...awesome-java