Reduce your boiler-plate code with SimpleFlatMapper
About me
No time for that sh*t, it's lightning talk!
Scuse me French.
@arnaudroger http://simpleflatmapper.org
SimpleFlatMapper
What ?
Maps flat structure
- CSV
- Jdbc ResultSet
- HSSFSheet
- jOOQ Record
- Datastax ResultSet
- ...
To POJOs with no configuration needed,
and no use of Unsafe and setAccessible.
No boxing either, no external dependencies.
@arnaudroger http://simpleflatmapper.org
SimpleFlatMapper
Inject via:
- Constructor
- Setter, everybody can do that.
- Field if public and non final.
- Factory method
- Builders
- Value type
- Inner Object
@arnaudroger http://simpleflatmapper.org
SimpleFlatMapper
But is it fast?
Yes super fast,
- generate bytecode using ASM*
- no boxing
- JIT can inline the cr*p out of it
* Unfortunatly due to the complexity of OSGI ClassLoader lifecycle ASM generation is disable when running in an OSGI container
PS : reflection call is not slow, lookup is.
@arnaudroger http://simpleflatmapper.org
SimpleFlatMapper
Less bullsh*t more code
let's look at JdbcTemplate example here.
@arnaudroger http://simpleflatmapper.org
The schema
@arnaudroger http://simpleflatmapper.org
The data
@arnaudroger http://simpleflatmapper.org
The data
So that query
Returns
@arnaudroger http://simpleflatmapper.org
Simple select
SELECT firstname, lastname
FROM users
Manual RowMapper
RowMapper<User> rm =
(rs, i) -> new User(
rs.getString("firstname"),
rs.getString("lastname"));
So far so good,
but only work when those 2 columns are present.
@arnaudroger http://simpleflatmapper.org
Simple select
Why not use BeanPropertyRowMapper?
as per javadoc
Please note that this class is designed to provide convenience rather than high performance. For best performance, consider using a custom RowMapper implementation.
It is the slowest mapper on the planet... don't use it.
@arnaudroger http://simpleflatmapper.org
Simple select - SFM
SFM RowMapper
RowMapper<User> rm =
JdbcTemplateMapperFactory
.newInstance()
.newRowMapper(User.class);
- adaptive, will map any column from the rs
- faster because it uses index lookup
Not convinced? I get you... next lets look at ....
<dependency>
<groupId>org.simpleflatmapper</groupId>
<artifactId>sfm-springjdbc</artifactId>
<version>3.11.8</version>
</dependency>
@arnaudroger http://simpleflatmapper.org
one-to-many?
- Not possible with RowMapper.
- Need ResultSetExtractor + RowMapper
@arnaudroger http://simpleflatmapper.org
one-to-many?
ResultSetExtractor + RowMapper
RowMapper<User> userRowMapper =
(rs, i) ->
new User(
rs.getInt("id"),
rs.getString("firstname"),
rs.getString("lastname"));
ResultSetExtractor<List<User>> rse = rs -> {
List<User> users = new ArrayList<>();
User currentUser = null;
while (rs.next()) {
int id = rs.getInt("id");
if (currentUser == null) { // initial object
currentUser = userRowMapper.mapRow(rs, 0);
} else if (currentUser.getId() != id) { // break
users.add(currentUser);
currentUser = userRowMapper.mapRow(rs, 0);
}
currentUser.getRoles().add(rs.getString("roles_name"));
}
if (currentUser != null) { // last object
users.add(currentUser);
}
return users;
};
@arnaudroger http://simpleflatmapper.org
one-to-many?
With SFM
ResultSetExtractor<List<User>> rse =
JdbcTemplateMapperFactory
.newInstance()
.addKeys("id")
.newResultSetExtractor(User.class);
Is that it?
can I have more joins?
see https://arnaudroger.github.io/blog/2017/03/02/jooq-one-to-many-without-dto.html
with example of mapping to
Tuple2<AuthorRecord,List<Tuple2<BookRecord,List<BookToBookStoreRecord>>>
@arnaudroger http://simpleflatmapper.org
Crud operation you ask?
JdbcTemplateCrud<User, Long> objectCrud =
JdbcTemplateMapperFactory.newInstance()
.crud(User.class, Integer.class)
.to(template, "users");
I can Create
objectCrud.create(user);
Read
objectCrud.read(2)
Update
objectCrud.update(user);
Delete
objectCrud.delete(2);
I have also batch insert - and upsert for postgres/mysql -
objectCrud.create(Arrays.asList(user1, user2));
objectCrud.createOrUpdate(Arrays.asList(user1, user2));
@arnaudroger http://simpleflatmapper.org
Fastest csv parser
Really ? are you using opencsv? supercsv drop that. the only ones worth considering are
- jackson-csv
- univocity - only for big file
- sfm-csv
@arnaudroger http://simpleflatmapper.org
Fastest csv parser
Benchmark time to parse a 3+ million rows csv
see http://simpleflatmapper.org/12-csv-performance.html
@arnaudroger http://simpleflatmapper.org
Mapping from a csv?
easy as that
try (Iterator<User> it =
CsvParser.mapTo(User.class).addKey("id").iterator(myFile)) {
while(it.hasNext()) {
User u = it.next();
}
}
PS: we currently only support
one join in a csv file. there is a
ticket for that
@arnaudroger http://simpleflatmapper.org
What else can it do?
-
Type conversion
-
Native UUID support
-
java time support
-
jOOL tuple support
-
Immutables, Lombok support
-
can map complex type like
-
Tuple2<User, List<String>>
-
-
Work on java 6, 7, 8 and 9!
-
as of recently supports protobuf object
@arnaudroger http://simpleflatmapper.org
Can you support a new flat structure?
Pretty easily, look at the code needed for jOOQ
Most of the work is done in sfm-map.
- Column key
- GetterFactory for map from
- SetterFactory for map to
- Some plumbing
@arnaudroger http://simpleflatmapper.org
Just give it a try.
it's MIT License, and get a few thousands download a month.
If you have any problem just raise an issue, or send an email on the empty google group.
@arnaudroger http://simpleflatmapper.org
Questions?
@arnaudroger http://simpleflatmapper.org
nidevconf-sfm
By Arnaud Roger
nidevconf-sfm
- 1,230