QuerydslBindings cannot bind multiple aliases to a path - jpa

Let's look at the code first, the following is how I bind two aliases to root.createdDate at the same time, but only one will always take effect, and the last alias endDate will always override the previous beginDate,I want both beginDate and endDate to be valid at the same time, what should I do?
#Override
default void customize(QuerydslBindings bindings, QPointLog root) {
bindings.bind(root.member.username, root.memo).first((path, value) -> path.likeIgnoreCase("%" + EscapeCharacter.of('!').escape(value) + "%", '!'));
// The following is how I bind multiple aliases to a path
bindings.bind(root.createdDate).as("beginDate").first((path, value) -> new BooleanBuilder(path.goe(value)));
bindings.bind(root.createdDate).as("endDate").first((path, value) -> new BooleanBuilder(path.loe(value))); // invalid
}

Related

Kafka Streams flatMapValues returns only one event in output

I am trying to split an incoming message to outgoing messages 1:N using flatMapValues() per docs here-> https://kafka.apache.org/20/javadoc/org/apache/kafka/streams/kstream/KStream.html#flatMapValues-org.apache.kafka.streams.kstream.ValueMapper-
However like the eg in the docs I can't return just a List of String but need to return a List of my AVRO type.
Sample input
k, "v1,v2,v3"
should produce an output like
k, v1
k, v2
k, v3
The input is a large string with comma separated values, so I split on , and then put each value in one output message, rest of the fields of the value for every output message will be the same including the key.
I tried this first:
.flatMapValues(new ValueMapper<work_reg_performer_int, Iterable<work_reg_performer_int>>() {
#Override
public Iterable<work_reg_performer_int> apply(work_reg_performer_int value) {
String[] ipifKeys = value.getIPIFkey().split(",");
List<work_reg_performer_int> result = new ArrayList<>(ipifKeys.length);
for (String ip : ipifKeys) {
value.setIPIFkey(ip);
result.add(value);
}
log.info("appended result size: {}",result.size());
return result;
}
But I only get k,v3 as the output event which I further join downstream with GlobalKTable.
Can you please tell me what's wrong with it, how do I return a List of values which are type AVRO.
Note that I generate AVRO types from maven avro plugin using my *.avsc files.
I also tried creating different objects of my AVRO type and putting them in the result list but now I just get the entire un-split string in the value.
workRegPerfInt
.filter((key, value) -> value.getIPIFkey()!=null && !Objects.equals(value.getIPIFkey(), ""))
.peek((k, v) -> log.info("after wpaaIpif join Key: {}, Value: {}", k, v))
.flatMapValues(new ValueMapper<work_reg_performer_int, Iterable<work_reg_performer_int>>() {
#Override
public Iterable<work_reg_performer_int> apply(work_reg_performer_int value) {
String[] ipifKeys = value.getIPIFkey().split(",");
List<work_reg_performer_int> result = new ArrayList<>(ipifKeys.length);
for (String ip : ipifKeys) {
work_reg_performer_int wp = new work_reg_performer_int();
wp.setIPIFkey(ip);
wp.setSequence(value.getSequence());
wp.setPerformerName(value.getPerformerName());
wp.setWrwhRrn(value.getWrwhRrn());
wp.setPrwhRrn(value.getPrwhRrn());
wp.setWinfkey(value.getWinfkey());
wp.setUpdatedBy(value.getUpdatedBy());
wp.setRegistrationHeaderId(value.getRegistrationHeaderId());
wp.setUpdatedDate(value.getUpdatedDate());
wp.setDeletedDate(value.getDeletedDate());
wp.setIsDelete(value.getIsDelete());
wp.setIsni(value.getIsni());
wp.setPerformanceLanguage(value.getPerformanceLanguage());
wp.setPerformerIpNameNo(value.getPerformerIpNameNo());
wp.setPerformerNameLanguage(value.getPerformerNameLanguage());
wp.setPerformerNameNonRoman(value.getPerformerNameNonRoman());
result.add(wp);
}
log.info("appended result size: {}",result.size());
return result;
}
});
What am I doing wrong please.
Thank you

How do I update a MongoDB document with new value using reactors Mono? (Kotlin)

So the context is that I require to update a value in a single document, I have a Mono, the parameter Object contains values such as username (to find the correct user by unique username) and an amount value.
The problem is that this value (due to other components of my application) is the value by which I need to increase/decrease the users balance, as opposed to passing a new balance. I intend to do this using two Monos where one finds the user, then this is combined to the other Mono with the inbound request, where I can then perform a simple sum (i.e balance + changeRequest.amount) then return this to the document database.
override fun increaseBalance(changeRequest: Mono<ChangeBalanceRequestResource>): Mono<ChangeBalanceResponse> {
val changeAmount: Mono<Decimal128> = changeRequest.map { it.transactionAmount }
val user: Mono<User> = changeRequest.flatMap { rxUserRepository.findByUsername(it.username)
val newBalace = user.map {
val r = changeAmount.block()
it.balance = sumBalance(it.balance!!, r!!)
rxUserRepository.save(it)
}
.flatMap { it }
.map { it.balance!! }
return Mono.just(ChangeBalanceResponse("success", newBalace.block()!!))
}
Obviously I'm trying to achieve this in a non-blocking fashion. I'm also open to using only a single Mono if that's possible/optimal. I also appreciate I've truly butchered the example and used .block as a placeholder to illustrate what I'm trying to achieve.
P.S this is my first post, so any tips on how to express my problem clearer would be useful.
Here's how I would do this in Java (Using Double instead of Decimal128):
public Mono<ChangeBalanceResponse> increaseBalance(Mono<ChangeBalanceRequestResource> changeRequest) {
Mono<Double> changeAmount = changeRequest.map(a -> a.transactionAmount());
Mono<User> user = changeRequest.map(a -> a.username()).flatMap(RxUserRepository::findByUsername);
return Mono.zip(changeAmount,user).flatMap(t2 -> {
Double changeAmount = t2.getT1();
User user = t2.getT2();
//assumes User is chained
return rxUserRepository.save(user.balance(sumBalance(changeAmount,user.balance())));
}).map(res -> new ChangeBalanceResponse("success",res.newBalance()))
}

How to compare Date in criteriaBuilder.greaterThan()?

I'm fixing a bug in JAVA/Angular Project, I'm getting a Date in Millisecodes from the front End, then I change the date from Millisecondes to "yyyy MM dd HH:mm:ss" format using SimpleDateFormat class in JAVA.
I want to compare the date that I'm getting from the front end with a field in a Table in my DataBase using criteriaBuilder.greaterThan().
The type of the field is bigInit(20).
I proposed as a solution to compare the dates using TimesTamp type, but the request from the client is a comparaison using Date in JAVA
public Specification<T> greater(Object value, String field, String type) {
return (root, criteriaQuery, criteriaBuilder) -> {
Path tuple = getPath(root, field);
System.out.println("type" + tuple.getJavaType());
if (tuple.getJavaType().isAssignableFrom(Date.class)) {
return criteriaBuilder.greaterThan(tuple, convertFilterDateToDate(value.toString()));
}
return criteriaBuilder.greaterThan(getPath(root,field),Double.valueOf(value.toString()));
};
}
This method takes 3 parametrs :
Object value : its type is Long in my case, it is the value of the date taken from the front End, I wrote a method to convert the value from Long to Date using SimpleDateFormat.
String field: its the field in my table, it contains dates with type Long.
String Type: it contains the value 'endDate' in my case.
Below, the definition of getPath Method :
public Path getPath(Root<T> root, String field){
String fiedls[] = field.split("\\.");
if(!field.contains(".")){
System.out.print(root.get(field));
return root.get(field);
}
else if (fiedls.length==2){
Join<Operation,Object> join = root.join(fiedls[0]);
return join.get(fiedls[1]);
}
else if(fiedls.length==3){
Join<Operation,Object> join = root.join(fiedls[0]);
Join<Object,Object> join1 = join.join(fiedls[1]);
return join1.get(fiedls[2]);
}
return null;
}
The request is to compare date using Date type in java and criteriaBuilder.greaterThan() , any Idea ?

Concatenating strings with RxJava2

I have a simple List of my POJO called Sport which has a name field .
What is the best way to concat all the names in the List?
Observable.just(member.getSports())
.map(sports -> {
StringBuilder builder = new StringBuilder();
for (Sport sport : sports) {
builder.append(sport.getName());
}
return builder.toString()
})
I believe there must be a better way ?
Willi Mentzel is right that you don't need Rx, but if you want to use it anyway in plain Java for readability, here's a cool way to leverage Rx2
// Get a list of sports names
Observable<String> names = Observable.fromIterable(member.getSports()).map(sport -> sport.getName())
// Concat list into a single string output separated by comma
Single<String> listOfNames = names.collect(StringBuilder::new, (sb, x) -> sb.append(x).append(", ")).map(StringBuilder::toString).toSingle()
One-liner in Java:
Observable.fromIterable(member.getSports()).map(sport -> sport.getName()).collect(StringBuilder::new, (sb, x) -> sb.append(x).append(", ")).map(StringBuilder::toString).toSingle()
One-liner in Kotlin with RxKotlin
member.getSports().map { it.name }.toObservable().collect(StringBuilder::new, (sb, x) -> sb.append(x).append(", ")).map(StringBuilder::toString).toSingle()
Produces:
volleyball, hockey, racquetball
You should always strive for code that is easy to read and therefore to maintain.
You don't need RxJava for that, just streams:
String joined = member.getSports().stream()
.map(sport -> sport.getName())
.collect(Collectors.joining(""));
Edit 1:
Since streams are not an option. I wouldn't use RxJava then anyways. Just use the code from inside your lambda.
StringBuilder builder = new StringBuilder();
for (Sport sport : sports) {
builder.append(sport.getName());
}
builder.toString()
Edit 2:
Or you build a more generalized version, in case you need a prefix and postfix as well:
// Inside Utils.java
public static <T> String joinToString(List<T> list, String separator, String prefix, String postfix, Function<T, String> func) {
StringBuilder builder = new StringBuilder();
builder.append(prefix);
if (!list.isEmpty()) {
for (T t : list.subList(0, list.size() - 1)) {
builder.append(func.apply(t));
builder.append(separator);
}
builder.append(list.get(list.size() - 1));
}
builder.append(postfix);
return builder.toString();
}
and use it like this:
Utils.joinToString(member.getSports(), "", "", "", Sport::getName));
This comes pretty close to Kotlin's joinToString extension function.

JSQL Parser - Info on parsing functions

Can JSQLParser differentiate between View/Function/Table in a SELECT query ?
If for example, executing a function in the following ways:
select * from public.new(10);
select public.new(10);
Is it possible for JSQL to figure out that it is executing a function and return that information?
The answer is: it depends.
JSqlParser is only a parser and does not have information about the database schema. In some databases parameterless functions are allowed to be called without parenthesis, e.g. select NOW (hope that is indeed a function ;)). In this case NOW would be accepted as a column name.
But JSqlParser supports parameterized functions, e.g. select testfunc(param1). In this case it will be accepted as a function.
Syntactically the usage of view and table is identical and JSqlParser is not able to differ between those. The view name would be accepted as a table name.
To get a differentiation:
first you would let JSqlParser parse your statement
extract all column names, table names, function names (a good start here is the TableNameFinder utility of JSqlParser)
get the final type you need to check it with your database schema
So here is a little example for point 1 and 2:
Statement statement = CCJSqlParserUtil.parse("select myfunc(5), now from public.new(10), mytable");
TablesNamesFinder tablesNamesFinder = new TablesNamesFinder() {
#Override
public void visit(Column tableColumn) {
System.out.println("column = " + tableColumn);
}
#Override
public void visit(Function function) {
System.out.println("function = " + function.getName());
super.visit(function);
}
#Override
public void visit(Table tableName) {
System.out.println("table = " + tableName.getFullyQualifiedName());
super.visit(tableName);
}
#Override
public void visit(TableFunction valuesList) {
System.out.println("table function = " + valuesList.getFunction().getName());
super.visit(valuesList);
}
};
System.out.println("all extracted tables=" + tablesNamesFinder.getTableList(statement));
and the result is:
function = myfunc
column = now
table function = public.new
table = mytable
all extracted tables=[mytable]