Last active
March 9, 2021 12:02
-
-
Save disc99/7f2c66270bf79d8e2f1630129a39c351 to your computer and use it in GitHub Desktop.
Doma one-to-many mapping
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.demo; | |
import lombok.EqualsAndHashCode; | |
import java.util.List; | |
import java.util.function.Function; | |
import static java.util.stream.Collectors.toList; | |
@EqualsAndHashCode | |
public class CacheKey<E> { | |
List<Function<E, Object>> type; | |
List<Object> value; | |
public CacheKey(List<Function<E, Object>> identifier, E entity) { | |
this.type = identifier; | |
this.value = identifier.stream() | |
.map(f -> f.apply(entity)) | |
.collect(toList()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.demo; | |
import lombok.Value; | |
import java.util.Map; | |
@Value | |
public class MappingObject<ENTITY, PARENT> { | |
ENTITY entity; | |
PARENT parent; | |
Map<CacheKey<ENTITY>, Object> cache; | |
public static <ENTITY, PARENT> MappingObject<ENTITY, PARENT> create(Map<CacheKey<ENTITY>, Object> cache, ENTITY entity, PARENT parent) { | |
return new MappingObject<>(entity, parent, cache); | |
} | |
public <CHILD> MappingObject<ENTITY, CHILD> child(CHILD child) { | |
return new MappingObject<>(entity, child, cache); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.demo; | |
import java.util.*; | |
import java.util.function.*; | |
import java.util.stream.Collector; | |
public class Mappings { | |
private static final Consumer NONE = t -> {}; | |
public static <T, R> Collector<T, ?, List<R>> entityMapping(Consumer<MappingObject<T, List<R>>> accumulator) { | |
Map<CacheKey<T>, Object> cache = new HashMap<>(); | |
return Collector.of( | |
ArrayList::new, | |
(list, t) -> accumulator.accept(MappingObject.create(cache, t, list)), | |
(List<R> l1, List<R> l2) -> { | |
l1.addAll(l2); | |
return l1; | |
} | |
); | |
} | |
@SuppressWarnings("unchecked") | |
public static <ENTITY, PARENT, OBJECT> MappingObject<ENTITY, PARENT> mapping(MappingObject<ENTITY, PARENT> mappingObject, List<Function<ENTITY, Object>> identifier, Function<ENTITY, OBJECT> creator, BiConsumer<PARENT, OBJECT> setter, Consumer<MappingObject<ENTITY, OBJECT>> nestedMapping) { | |
if (identifier.stream().allMatch(f -> f.apply(mappingObject.getEntity()) != null)) { | |
OBJECT object = (OBJECT) mappingObject.getCache().computeIfAbsent(new CacheKey<>(identifier, mappingObject.getEntity()), k -> { | |
OBJECT o = creator.apply(mappingObject.getEntity()); | |
setter.accept(mappingObject.getParent(), o); | |
return o; | |
}); | |
nestedMapping.accept(mappingObject.child(object)); | |
} | |
return mappingObject; | |
} | |
@SuppressWarnings("unchecked") | |
public static <ENTITY, PARENT, OBJECT> MappingObject<ENTITY, PARENT> mapping(MappingObject<ENTITY, PARENT> mappingObject, List<Function<ENTITY, Object>> identifier, Function<ENTITY, OBJECT> creator, BiConsumer<PARENT, OBJECT> setter) { | |
return mapping(mappingObject, identifier, creator, setter, NONE); | |
} | |
@SuppressWarnings("unchecked") | |
public static <ENTITY, PARENT, OBJECT> PARENT mapping(Map<CacheKey<ENTITY>, Object> cache, ENTITY entity, PARENT parent, List<Function<ENTITY, Object>> identifier, Function<ENTITY, OBJECT> creator, BiConsumer<PARENT, OBJECT> setter, Consumer<OBJECT> nestedMapping) { | |
if (identifier.stream().allMatch(f -> f.apply(entity) != null)) { | |
OBJECT object = (OBJECT) cache.computeIfAbsent(new CacheKey<>(identifier, entity), k -> { | |
OBJECT o = creator.apply(entity); | |
setter.accept(parent, o); | |
return o; | |
}); | |
nestedMapping.accept(object); | |
} | |
return parent; | |
} | |
@SuppressWarnings("unchecked") | |
public static <ENTITY, PARENT, OBJECT> PARENT mapping(Map<CacheKey<ENTITY>, Object> cache, ENTITY entity, PARENT parent, List<Function<ENTITY, Object>> identifier, Function<ENTITY, OBJECT> creator, BiConsumer<PARENT, OBJECT> setter) { | |
return mapping(cache, entity, parent, identifier, creator, setter, (Consumer<OBJECT>) NONE); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.demo; | |
import com.fasterxml.jackson.databind.ObjectMapper; | |
import com.fasterxml.jackson.databind.ObjectWriter; | |
import org.junit.jupiter.api.Test; | |
import java.util.*; | |
import java.util.function.BiConsumer; | |
import java.util.function.BinaryOperator; | |
import java.util.function.Function; | |
import java.util.stream.Collector; | |
import static com.example.demo.Mappings.*; | |
import static org.junit.jupiter.api.Assertions.assertEquals; | |
public class MappingTest { | |
List<ResultEntity> entities = List.of( | |
new ResultEntity(1, "user1", 1, "tweet1", 1, "comment1", 1, new Date(1)), | |
new ResultEntity(1, "user1", 1, "tweet1", 1, "comment1", 2, new Date(2)), | |
new ResultEntity(2, "user2", 2, "tweet2", 2, "comment2", 3, new Date(3)), | |
new ResultEntity(2, "user2", 2, "tweet2", 3, "comment3", 3, new Date(3)), | |
new ResultEntity(2, "user2", 2, "tweet2", 4, "comment4", 3, new Date(3)), | |
new ResultEntity(2, "user2", 2, "tweet2", 2, "comment2", 4, new Date(4)), | |
new ResultEntity(2, "user2", 2, "tweet2", 3, "comment3", 4, new Date(4)), | |
new ResultEntity(2, "user2", 2, "tweet2", 4, "comment4", 4, new Date(4)), | |
new ResultEntity(3, "user3", 4, "tweet4", null, null, null, null), | |
new ResultEntity(2, "user2", 5, "tweet5", null, null, null, null), | |
new ResultEntity(4, "user4", null, null, null, null, null, null) | |
); | |
List<User> expected = List.of( | |
new User(1, "user1", List.of( | |
new Tweet(1, "tweet1", List.of( | |
new Comment(1, "comment1") | |
), List.of( | |
new Like(1, new Date(1)), | |
new Like(2, new Date(2)) | |
)) | |
)), | |
new User(2, "user2", List.of( | |
new Tweet(2, "tweet2", List.of( | |
new Comment(2, "comment2"), | |
new Comment(3, "comment3"), | |
new Comment(4, "comment4") | |
), List.of( | |
new Like(3, new Date(3)), | |
new Like(4, new Date(4)) | |
)), | |
new Tweet(5, "tweet5", List.of(), List.of()) | |
)), | |
new User(3, "user3", List.of(new Tweet(4, "tweet4", List.of(), List.of()))), | |
new User(4, "user4", List.of()) | |
); | |
static class UserDao { | |
List<ResultEntity> entities; | |
public UserDao(List<ResultEntity> entities) { | |
this.entities = entities; | |
} | |
List<ResultEntity> findUserList() { | |
return entities; | |
}; | |
<R> R findUserCollect(Collector<ResultEntity, ?, R> collector) { | |
return entities.stream().collect(collector); | |
} | |
} | |
UserDao userDao = new UserDao(entities); | |
@Test | |
void test__01_基本的なマッピング() throws Exception { | |
List<ResultEntity> userList = userDao.findUserList(); | |
List<User> users = new ArrayList<>(); | |
for (ResultEntity entity : userList) { | |
User user = null; | |
for (User u : users) { | |
if (u.getId().equals(entity.getUserId())) { | |
user = u; | |
} | |
} | |
if (user == null) { | |
user = new User(entity.getUserId(), entity.getUserName(), new ArrayList<>()); | |
users.add(user); | |
} | |
if (entity.getTweetId() != null) { | |
Tweet tweet = null; | |
for (Tweet t : user.getTweets()) { | |
if (t.getId().equals(entity.getTweetId())) { | |
tweet = t; | |
} | |
} | |
if (tweet == null) { | |
tweet = new Tweet(entity.getTweetId(), entity.getTweet(), new ArrayList<>(), new ArrayList<>()); | |
user.getTweets().add(tweet); | |
} | |
if (entity.getCommentId() != null) { | |
List<Comment> comments = tweet.getComments(); | |
if (comments.stream().noneMatch(c -> c.getId().equals(entity.getCommentId()))) { | |
comments.add(new Comment(entity.getCommentId(), entity.getComment())); | |
} | |
} | |
if (entity.getLikeId() != null) { | |
List<Like> likes = tweet.getLikes(); | |
if (likes.stream().noneMatch(c -> c.getId().equals(entity.getLikeId()))) { | |
likes.add(new Like(entity.getLikeId(), entity.getLikeTime())); | |
} | |
} | |
} | |
} | |
assertJson(users, expected); | |
} | |
@Test | |
void test__02_Streamの利用() throws Exception { | |
List<User> users = userDao.findUserList().stream() | |
.reduce(new ArrayList<>(), (list, entity) -> { | |
User user = null; | |
for (User u : list) { | |
if (u.getId().equals(entity.getUserId())) { | |
user = u; | |
} | |
} | |
if (user == null) { | |
user = new User(entity.getUserId(), entity.getUserName(), new ArrayList<>()); | |
list.add(user); | |
} | |
if (entity.getTweetId() == null) { | |
return list; | |
} | |
Tweet tweet = null; | |
for (Tweet t : user.getTweets()) { | |
if (t.getId().equals(entity.getTweetId())) { | |
tweet = t; | |
} | |
} | |
if (tweet == null) { | |
tweet = new Tweet(entity.getTweetId(), entity.getTweet(), new ArrayList<>(), new ArrayList<>()); | |
user.getTweets().add(tweet); | |
} | |
if (entity.getCommentId() != null) { | |
List<Comment> comments = tweet.getComments(); | |
if (comments.stream().noneMatch(c -> c.getId().equals(entity.getCommentId()))) { | |
comments.add(new Comment(entity.getCommentId(), entity.getComment())); | |
} | |
} | |
if (entity.getLikeId() != null) { | |
List<Like> likes = tweet.getLikes(); | |
if (likes.stream().noneMatch(c -> c.getId().equals(entity.getLikeId()))) { | |
likes.add(new Like(entity.getLikeId(), entity.getLikeTime())); | |
} | |
} | |
return list; | |
}, (BinaryOperator<List<User>>) Lists::concat); | |
assertJson(users, expected); | |
} | |
@Test | |
void test__03_キャッシュを利用したマッピング() throws Exception { | |
Map<Object, Object> cache = new HashMap<>(); | |
List<User> users = userDao.findUserList().stream() | |
.reduce(new ArrayList<>(), (list, entity) -> { | |
if (entity.getUserId() != null) { | |
User user = (User) cache.get("userId:" + entity.getUserId()); | |
if (user == null) { | |
user = new User(entity.getUserId(), entity.getUserName(), new ArrayList<>()); | |
cache.put("userId:" + entity.getUserId(), user); | |
list.add(user); | |
} | |
if (entity.getTweetId() != null) { | |
Tweet tweet = (Tweet) cache.get("userId:" + entity.getUserId() + "tweetId:" + entity.getTweetId()); | |
if (tweet == null) { | |
tweet = new Tweet(entity.getTweetId(), entity.getTweet(), new ArrayList<>(), new ArrayList<>()); | |
cache.put("userId:" + entity.getUserId() + "tweetId:" + entity.getTweetId(), tweet); | |
user.getTweets().add(tweet); | |
} | |
if (entity.getCommentId() != null) { | |
Comment comment = (Comment) cache.get("userId:" + entity.getUserId() + "tweetId:" + entity.getTweetId() + "commentId" + entity.getCommentId()); | |
if (comment == null) { | |
comment = new Comment(entity.getCommentId(), entity.getComment()); | |
cache.put("userId:" + entity.getUserId() + "tweetId:" + entity.getTweetId() + "commentId" + entity.getCommentId(), comment); | |
tweet.getComments().add(comment); | |
} | |
} | |
if (entity.getLikeId() != null) { | |
Like like = (Like) cache.get("userId:" + entity.getUserId() + "tweetId:" + entity.getTweetId() + "likeId" + entity.getLikeId()); | |
if (like == null) { | |
like = new Like(entity.getLikeId(), entity.getLikeTime()); | |
cache.put("userId:" + entity.getUserId() + "tweetId:" + entity.getTweetId() + "likeId" + entity.getLikeId(), like); | |
tweet.getLikes().add(like); | |
} | |
} | |
} | |
} | |
return list; | |
}, (BinaryOperator<List<User>>) Lists::concat); | |
assertJson(users, expected); | |
} | |
@Test | |
void test__03_キャッシュを汎用化() throws Exception { | |
List<Function<ResultEntity, Object>> userKey = List.of(ResultEntity::getUserId); | |
List<Function<ResultEntity, Object>> tweetKey = List.of(ResultEntity::getUserId, ResultEntity::getTweetId); | |
List<Function<ResultEntity, Object>> commentKey = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getCommentId); | |
List<Function<ResultEntity, Object>> likeKey = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getLikeId); | |
Map<CacheKey<ResultEntity>, Object> cache = new HashMap<>(); | |
List<User> users = userDao.findUserList().stream() | |
.reduce(new ArrayList<>(), (list, entity) -> { | |
if (entity.getUserId() != null) { | |
User user = (User) cache.get(new CacheKey<>(userKey, entity)); | |
if (user == null) { | |
user = new User(entity.getUserId(), entity.getUserName(), new ArrayList<>()); | |
cache.put(new CacheKey<>(userKey, entity), user); | |
list.add(user); | |
} | |
if (entity.getTweetId() != null) { | |
Tweet tweet = (Tweet) cache.get(new CacheKey<>(tweetKey, entity)); | |
if (tweet == null) { | |
tweet = new Tweet(entity.getTweetId(), entity.getTweet(), new ArrayList<>(), new ArrayList<>()); | |
cache.put(new CacheKey<>(tweetKey, entity), tweet); | |
user.getTweets().add(tweet); | |
} | |
if (entity.getCommentId() != null) { | |
Comment comment = (Comment) cache.get(new CacheKey<>(commentKey, entity)); | |
if (comment == null) { | |
comment = new Comment(entity.getCommentId(), entity.getComment()); | |
cache.put(new CacheKey<>(commentKey, entity), comment); | |
tweet.getComments().add(comment); | |
} | |
} | |
if (entity.getLikeId() != null) { | |
Like like = (Like) cache.get(new CacheKey<>(likeKey, entity)); | |
if (like == null) { | |
like = new Like(entity.getLikeId(), entity.getLikeTime()); | |
cache.put(new CacheKey<>(likeKey, entity), like); | |
tweet.getLikes().add(like); | |
} | |
} | |
} | |
} | |
return list; | |
}, (BinaryOperator<List<User>>) Lists::concat); | |
assertJson(users, expected); | |
} | |
@Test | |
void test__04_処理の汎用化() throws Exception { | |
List<Function<ResultEntity, Object>> userIdentifier = List.of(ResultEntity::getUserId); | |
List<Function<ResultEntity, Object>> tweetIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId); | |
List<Function<ResultEntity, Object>> commentIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getCommentId); | |
List<Function<ResultEntity, Object>> likeIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getLikeId); | |
Function<ResultEntity, User> userCreator = entity -> new User(entity.getUserId(), entity.getUserName(), new ArrayList<>()); | |
Function<ResultEntity, Tweet> tweetCreator = entity -> new Tweet(entity.getTweetId(), entity.getTweet(), new ArrayList<>(), new ArrayList<>()); | |
Function<ResultEntity, Comment> commentCreator = entity -> new Comment(entity.getCommentId(), entity.getComment()); | |
Function<ResultEntity, Like> likeCreator = entity -> new Like(entity.getLikeId(), entity.getLikeTime()); | |
BiConsumer<List<User>, User> userSetter = List::add; | |
BiConsumer<User, Tweet> tweetSetter = (parent, object) -> parent.getTweets().add(object); | |
BiConsumer<Tweet, Comment> commentSetter = (parent, object) -> parent.getComments().add(object); | |
BiConsumer<Tweet, Like> likeSetter = (parent, object) -> parent.getLikes().add(object); | |
Map<CacheKey<ResultEntity>, Object> cache = new HashMap<>(); | |
List<User> users = userDao.findUserList().stream() | |
.reduce(new ArrayList<>(), (list, entity) -> { | |
if (userIdentifier.stream().allMatch(f -> f.apply(entity) != null)) { | |
User user = (User) cache.computeIfAbsent(new CacheKey<>(userIdentifier, entity), key -> { | |
User e = userCreator.apply(entity); | |
userSetter.accept(list, e); | |
return e; | |
}); | |
if (tweetIdentifier.stream().allMatch(f -> f.apply(entity) != null)) { | |
Tweet tweet = (Tweet) cache.computeIfAbsent(new CacheKey<>(tweetIdentifier, entity), key -> { | |
Tweet e = tweetCreator.apply(entity); | |
tweetSetter.accept(user, e); | |
return e; | |
}); | |
if (commentIdentifier.stream().allMatch(f -> f.apply(entity) != null)) { | |
cache.computeIfAbsent(new CacheKey<>(commentIdentifier, entity), key -> { | |
Comment e = commentCreator.apply(entity); | |
commentSetter.accept(tweet, e); | |
return e; | |
}); | |
} | |
if (likeIdentifier.stream().allMatch(f -> f.apply(entity) != null)) { | |
cache.computeIfAbsent(new CacheKey<>(likeIdentifier, entity), key -> { | |
Like e = likeCreator.apply(entity); | |
likeSetter.accept(tweet, e); | |
return e; | |
}); | |
} | |
} | |
} | |
return list; | |
}, (BinaryOperator<List<User>>) Lists::concat); | |
assertJson(users, expected); | |
} | |
@Test | |
void test__05_共通化() throws Exception { | |
List<Function<ResultEntity, Object>> userIdentifier = List.of(ResultEntity::getUserId); | |
List<Function<ResultEntity, Object>> tweetIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId); | |
List<Function<ResultEntity, Object>> commentIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getCommentId); | |
List<Function<ResultEntity, Object>> likeIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getLikeId); | |
Function<ResultEntity, User> userCreator = entity -> new User(entity.getUserId(), entity.getUserName(), new ArrayList<>()); | |
Function<ResultEntity, Tweet> tweetCreator = entity -> new Tweet(entity.getTweetId(), entity.getTweet(), new ArrayList<>(), new ArrayList<>()); | |
Function<ResultEntity, Comment> commentCreator = entity -> new Comment(entity.getCommentId(), entity.getComment()); | |
Function<ResultEntity, Like> likeCreator = entity -> new Like(entity.getLikeId(), entity.getLikeTime()); | |
BiConsumer<List<User>, User> userSetter = List::add; | |
BiConsumer<User, Tweet> tweetSetter = (parent, object) -> parent.getTweets().add(object); | |
BiConsumer<Tweet, Comment> commentSetter = (parent, object) -> parent.getComments().add(object); | |
BiConsumer<Tweet, Like> likeSetter = (parent, object) -> parent.getLikes().add(object); | |
Map<CacheKey<ResultEntity>, Object> cache = new HashMap<>(); | |
List<User> users = userDao.findUserList().stream().reduce(new ArrayList<>(), | |
(list, entity) -> mapping(cache, entity, list, userIdentifier, userCreator, userSetter, | |
user -> mapping(cache, entity, user, tweetIdentifier, tweetCreator, tweetSetter, | |
tweet -> { | |
mapping(cache, entity, tweet, commentIdentifier, commentCreator, commentSetter); | |
mapping(cache, entity, tweet, likeIdentifier, likeCreator, likeSetter); | |
})) | |
, (BinaryOperator<List<User>>) Lists::concat); | |
assertJson(users, expected); | |
} | |
@Test | |
void test__06_Collectorの利用() throws Exception { | |
List<Function<ResultEntity, Object>> userIdentifier = List.of(ResultEntity::getUserId); | |
List<Function<ResultEntity, Object>> tweetIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId); | |
List<Function<ResultEntity, Object>> commentIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getCommentId); | |
List<Function<ResultEntity, Object>> likeIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getLikeId); | |
Function<ResultEntity, User> userCreator = entity -> new User(entity.getUserId(), entity.getUserName(), new ArrayList<>()); | |
Function<ResultEntity, Tweet> tweetCreator = entity -> new Tweet(entity.getTweetId(), entity.getTweet(), new ArrayList<>(), new ArrayList<>()); | |
Function<ResultEntity, Comment> commentCreator = entity -> new Comment(entity.getCommentId(), entity.getComment()); | |
Function<ResultEntity, Like> likeCreator = entity -> new Like(entity.getLikeId(), entity.getLikeTime()); | |
BiConsumer<List<User>, User> userSetter = List::add; | |
BiConsumer<User, Tweet> tweetSetter = (parent, object) -> parent.getTweets().add(object); | |
BiConsumer<Tweet, Comment> commentSetter = (parent, object) -> parent.getComments().add(object); | |
BiConsumer<Tweet, Like> likeSetter = (parent, object) -> parent.getLikes().add(object); | |
Map<CacheKey<ResultEntity>, Object> cache = new HashMap<>(); | |
List<User> users = userDao.findUserList().stream().collect(Collector.of(ArrayList::new, | |
(list, entity) -> mapping(cache, entity, list, userIdentifier, userCreator, userSetter, | |
user -> mapping(cache, entity, user, tweetIdentifier, tweetCreator, tweetSetter, | |
tweet -> { | |
mapping(cache, entity, tweet, commentIdentifier, commentCreator, commentSetter); | |
mapping(cache, entity, tweet, likeIdentifier, likeCreator, likeSetter); | |
})) | |
, (BinaryOperator<List<User>>) Lists::concat)); | |
assertJson(users, expected); | |
} | |
@Test | |
void test__06_Collectorの汎用化() throws Exception { | |
List<Function<ResultEntity, Object>> userIdentifier = List.of(ResultEntity::getUserId); | |
List<Function<ResultEntity, Object>> tweetIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId); | |
List<Function<ResultEntity, Object>> commentIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getCommentId); | |
List<Function<ResultEntity, Object>> likeIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getLikeId); | |
Function<ResultEntity, User> userCreator = entity -> new User(entity.getUserId(), entity.getUserName(), new ArrayList<>()); | |
Function<ResultEntity, Tweet> tweetCreator = entity -> new Tweet(entity.getTweetId(), entity.getTweet(), new ArrayList<>(), new ArrayList<>()); | |
Function<ResultEntity, Comment> commentCreator = entity -> new Comment(entity.getCommentId(), entity.getComment()); | |
Function<ResultEntity, Like> likeCreator = entity -> new Like(entity.getLikeId(), entity.getLikeTime()); | |
BiConsumer<List<User>, User> userSetter = List::add; | |
BiConsumer<User, Tweet> tweetSetter = (parent, object) -> parent.getTweets().add(object); | |
BiConsumer<Tweet, Comment> commentSetter = (parent, object) -> parent.getComments().add(object); | |
BiConsumer<Tweet, Like> likeSetter = (parent, object) -> parent.getLikes().add(object); | |
Map<CacheKey<ResultEntity>, Object> cache = new HashMap<>(); | |
List<User> users = userDao.findUserList().stream().collect(reduceBy( | |
(list, entity) -> mapping(cache, entity, list, userIdentifier, userCreator, userSetter, | |
user -> mapping(cache, entity, user, tweetIdentifier, tweetCreator, tweetSetter, | |
tweet -> { | |
mapping(cache, entity, tweet, commentIdentifier, commentCreator, commentSetter); | |
mapping(cache, entity, tweet, likeIdentifier, likeCreator, likeSetter); | |
})))); | |
assertJson(users, expected); | |
} | |
@Test | |
void test__07_キャッシュの抽象化() throws Exception { | |
List<Function<ResultEntity, Object>> userIdentifier = List.of(ResultEntity::getUserId); | |
List<Function<ResultEntity, Object>> tweetIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId); | |
List<Function<ResultEntity, Object>> commentIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getCommentId); | |
List<Function<ResultEntity, Object>> likeIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getLikeId); | |
Function<ResultEntity, User> userCreator = entity -> new User(entity.getUserId(), entity.getUserName(), new ArrayList<>()); | |
Function<ResultEntity, Tweet> tweetCreator = entity -> new Tweet(entity.getTweetId(), entity.getTweet(), new ArrayList<>(), new ArrayList<>()); | |
Function<ResultEntity, Comment> commentCreator = entity -> new Comment(entity.getCommentId(), entity.getComment()); | |
Function<ResultEntity, Like> likeCreator = entity -> new Like(entity.getLikeId(), entity.getLikeTime()); | |
BiConsumer<List<User>, User> userSetter = List::add; | |
BiConsumer<User, Tweet> tweetSetter = (parent, object) -> parent.getTweets().add(object); | |
BiConsumer<Tweet, Comment> commentSetter = (parent, object) -> parent.getComments().add(object); | |
BiConsumer<Tweet, Like> likeSetter = (parent, object) -> parent.getLikes().add(object); | |
Map<CacheKey<ResultEntity>, Object> cache = new HashMap<>(); | |
List<User> users = userDao.findUserList().stream().collect(reduceBy( | |
(list, entity) -> mapping(MappingObject.create(cache, entity, list), userIdentifier, userCreator, userSetter, | |
user -> mapping(user, tweetIdentifier, tweetCreator, tweetSetter, | |
tweet -> { | |
mapping(tweet, commentIdentifier, commentCreator, commentSetter); | |
mapping(tweet, likeIdentifier, likeCreator, likeSetter); | |
})))); | |
assertJson(users, expected); | |
} | |
@Test | |
void test__07_キャッシュの隠蔽() throws Exception { | |
List<Function<ResultEntity, Object>> userIdentifier = List.of(ResultEntity::getUserId); | |
List<Function<ResultEntity, Object>> tweetIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId); | |
List<Function<ResultEntity, Object>> commentIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getCommentId); | |
List<Function<ResultEntity, Object>> likeIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getLikeId); | |
Function<ResultEntity, User> userCreator = entity -> new User(entity.getUserId(), entity.getUserName(), new ArrayList<>()); | |
Function<ResultEntity, Tweet> tweetCreator = entity -> new Tweet(entity.getTweetId(), entity.getTweet(), new ArrayList<>(), new ArrayList<>()); | |
Function<ResultEntity, Comment> commentCreator = entity -> new Comment(entity.getCommentId(), entity.getComment()); | |
Function<ResultEntity, Like> likeCreator = entity -> new Like(entity.getLikeId(), entity.getLikeTime()); | |
BiConsumer<List<User>, User> userSetter = List::add; | |
BiConsumer<User, Tweet> tweetSetter = (parent, object) -> parent.getTweets().add(object); | |
BiConsumer<Tweet, Comment> commentSetter = (parent, object) -> parent.getComments().add(object); | |
BiConsumer<Tweet, Like> likeSetter = (parent, object) -> parent.getLikes().add(object); | |
List<User> users = userDao.findUserList().stream().collect(entityMapping( | |
list -> mapping(list, userIdentifier, userCreator, userSetter, | |
user -> mapping(user, tweetIdentifier, tweetCreator, tweetSetter, | |
tweet -> { | |
mapping(tweet, commentIdentifier, commentCreator, commentSetter); | |
mapping(tweet, likeIdentifier, likeCreator, likeSetter); | |
})))); | |
assertJson(users, expected); | |
} | |
@Test | |
void test__07_キャッシュの隠蔽とインライン化() throws Exception { | |
List<Function<ResultEntity, Object>> userIdentifier = List.of(ResultEntity::getUserId); | |
List<Function<ResultEntity, Object>> tweetIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId); | |
List<Function<ResultEntity, Object>> commentIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getCommentId); | |
List<Function<ResultEntity, Object>> likeIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getLikeId); | |
List<User> users = userDao.findUserList().stream().collect(entityMapping( | |
list -> mapping(list, userIdentifier, | |
entity -> new User(entity.getUserId(), entity.getUserName(), new ArrayList<>()), | |
List::add, | |
user -> mapping(user, tweetIdentifier, | |
entity -> new Tweet(entity.getTweetId(), entity.getTweet(), new ArrayList<>(), new ArrayList<>()), | |
(parent, object) -> parent.getTweets().add(object), | |
tweet -> { | |
mapping(tweet, commentIdentifier, | |
entity -> new Comment(entity.getCommentId(), entity.getComment()), | |
(parent, object) -> parent.getComments().add(object)); | |
mapping(tweet, likeIdentifier, | |
entity -> new Like(entity.getLikeId(), entity.getLikeTime()), | |
(parent, object) -> parent.getLikes().add(object)); | |
})))); | |
assertJson(users, expected); | |
} | |
@Test | |
void test__08_collect検索() throws Exception { | |
List<Function<ResultEntity, Object>> userIdentifier = List.of(ResultEntity::getUserId); | |
List<Function<ResultEntity, Object>> tweetIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId); | |
List<Function<ResultEntity, Object>> commentIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getCommentId); | |
List<Function<ResultEntity, Object>> likeIdentifier = List.of(ResultEntity::getUserId, ResultEntity::getTweetId, ResultEntity::getLikeId); | |
List<User> users = userDao.findUserCollect(entityMapping( | |
list -> mapping(list, userIdentifier, | |
entity -> new User(entity.getUserId(), entity.getUserName(), new ArrayList<>()), | |
List::add, | |
user -> mapping(user, tweetIdentifier, | |
entity -> new Tweet(entity.getTweetId(), entity.getTweet(), new ArrayList<>(), new ArrayList<>()), | |
(parent, object) -> parent.getTweets().add(object), | |
tweet -> { | |
mapping(tweet, commentIdentifier, | |
entity -> new Comment(entity.getCommentId(), entity.getComment()), | |
(parent, object) -> parent.getComments().add(object)); | |
mapping(tweet, likeIdentifier, | |
entity -> new Like(entity.getLikeId(), entity.getLikeTime()), | |
(parent, object) -> parent.getLikes().add(object)); | |
})))); | |
assertJson(users, expected); | |
} | |
private void assertJson(List<User> users, List<User> expected) throws Exception { | |
ObjectWriter objectWriter = new ObjectMapper().writerWithDefaultPrettyPrinter(); | |
assertEquals( | |
objectWriter.writeValueAsString(expected), | |
objectWriter.writeValueAsString(users) | |
); | |
} | |
static class Lists { | |
static <T> List<T> concat(List<T> list1, List<T> list2) { | |
list1.addAll(list2); | |
return list1; | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment