How can I get multi-line queries to be injected? It works on Room with Java classes, but does Kotlin support this as well?
E.g. I have 2 queries here, and only the top SQL query (1 line) gets injected.
I tried to follow the steps in this guide but could not find the required settings.
There is an issue at https://youtrack.jetbrains.com/issue/KT-13636 which suggests this is fixed, but I'm not sure how to implement the fix.
You can use a raw string which is more readable anyway:
#Dao
interface ItemDao {
#Query("""
SELECT * FROM Item
WHERE Item.id = :id
""")
fun loadItemById(id: Long): LiveData<Item>
}
Related
I currently use junit5, wiremock and restassured for my integration tests. Karate looks very promising, yet I am struggling with the setup of data-driven tests a bit as I need to prepare a nested data structures which, in the current setup, looks like the following:
abstract class StationRequests(val stations: Collection<String>): ArgumentsProvider {
override fun provideArguments(context: ExtensionContext): java.util.stream.Stream<out Arguments>{
val now = LocalDateTime.now()
val samples = mutableListOf<Arguments>()
stations.forEach { station ->
Subscription.values().forEach { subscription ->
listOf(
*Device.values(),
null
).forEach { device ->
Stream.Protocol.values().forEach { protocol ->
listOf(
null,
now.minusMinutes(5),
now.minusHours(2),
now.minusDays(1)
).forEach { startTime ->
samples.add(
Arguments.of(
subscription, device, station, protocol, startTime
)
)
}
}
}
}
}
return java.util.stream.Stream.of(*samples.toTypedArray())
}
}
Is there any preferred way how to setup such nested data structures with karate? I initially thought about defining 5 different arrays with sample values for subscription, device, station, protocol and startTime and to combine and merge them into a single array which would be used in the Examples: section.
I did not succeed so far though and I am wondering if there is a better way to prepare such nested data driven tests?
I don't recommend nesting unless absolutely necessary. You may be able to "flatten" your permutations into a single table, something like this: https://github.com/intuit/karate/issues/661#issue-402624580
That said, look out for the alternate option to Examples: which just might work for your case: https://github.com/intuit/karate#data-driven-features
EDIT: In version 1.3.0, a new #setup life cycle was introduced that changes the example below a bit.
Here's a simple example:
Feature:
Scenario:
* def data = [{ rows: [{a: 1},{a: 2}] }, { rows: [{a: 3},{a: 4}] }]
* call read('called.feature#one') data
and this is: called.feature:
#ignore
Feature:
#one
Scenario:
* print 'one:', __loop
* call read('called.feature#two') rows
#two
Scenario:
* print 'two:', __loop
* print 'value of a:', a
This is how it looks like in the new HTML report (which is in 0.9.6.RC2 and may need more fine tuning) and it shows off how Karate can support "nesting" even in the report, which Cucumber cannot do. Maybe you can provide feedback and let us know if it is ready for release :)
Here I try to make call from database and combine into new mono from different mono and flux.
public Mono<ListMovieWithKomenDTO> fetchMovieAndKomen(Integer movieId){
Mono<Movie> movie = findById(movieId).subscribeOn(Schedulers.elastic());
Flux<MovieKomen> movieKomen = getKomenByMovieId(movieId).subscribeOn(Schedulers.elastic());
return Mono.zip(movie, movieKomen.collectList(), movieMovieKomenDTOBiFunction);
}
private BiFunction<Movie, List<MovieKomen>, ListMovieWithKomenDTO> movieMovieKomenDTOBiFunction = (x1, x2) -> ListMovieWithKomenDTO.builder()
// .age(x1.getAge())
.id(x1.getId())
.name(x1.getName())
.status(x1.getStatus())
.detail(x1.getDetail())
.url(x1.getUrl())
.movieKomen(x2).build();
In here I make db call twice for header ( like movie ) and detail ( like movie comment ) to separate them. After I make retrieve two different data, I want to join into new mono data based on flux data and mono. to make them into one data, I make DTO to put together from movie table and comment table but it failed. I assume that errors from mono.zip to get data into one new mono.
Here the error from debug console
java.lang.IllegalArgumentException: Cannot encode parameter of type org.springframework.r2dbc.core.Parameter
at io.r2dbc.postgresql.ExtendedQueryPostgresqlStatement.bind(ExtendedQueryPostgresqlStatement.java:89) ~[r2dbc-postgresql-0.8.10.RELEASE.jar:0.8.10.RELEASE]
Thank you
Problem is in my repository I used
public interface MovieKomenRepository extends ReactiveCrudRepository<MovieKomen,Integer> {
#Query("select * from m_movie_komen where m_movie_id = $1")
Flux<MovieKomen> findByMovieId(int movie_id);
}
in above example, I used $1 for the param in query. But when I change my code like bottom. It works like a charm.
public interface MovieKomenRepository extends ReactiveCrudRepository<MovieKomen,Integer> {
#Query("select * from m_movie_komen where m_movie_id = :movie")
Flux<MovieKomen> findByMovieId(#Param("movie") int movie_id);
}
so if someone want to use my service code is fine but careful in repository. we should not used '$1' instead ':movie'. so the problem not in service or mono/flux. but in my repository
Thank you.
Can I use Pageable attribute in Spring Data R2dbc repositories with #Query annotation? For example;
public interface PartyRepository extends ReactiveCrudRepository<Party,String> {
#Query("select * from party order by id")
Flux<Party> getParties(Pageable pageable);
}
It gives "org.springframework.data.repository.query.ParameterOutOfBoundsException : Invalid parameter index! You seem to have declared too little query method parameteres!"
Is there any way to use pagination in spring Data R2dbc repositories?
Thanks.
This is not supported by R2DBC and probably never will.
But you can adjust the query string with SpEL expressions manually to include paging. For MySQL, in your example, this could look like this:
#Query("SELECT * FROM party ORDER BY id LIMIT :#{[0].offset},:#{[0].pageSize}")
Flux<Party> getParties(Pageable pageable);
The [0] part indicates which argument in your argument list is the Pageable.
I am a new to using Mongo DB and exploring the frameworks around for migrating from mysql to mongodb. So far from my findings I have been able to figure out SpringMongo as the best solution to my requirements.
The only problem is that instead of using a DSL based or abstract querying mechanism, I wished the framework allowed me to pass plain json string as arguments to the different methods exposed by the API(find, findOne) so that the query parameters can be written out to an external file (using a key to refer) and passed to the methods by reading and parsing at run time. But the framework should be capable of mapping the results to the domain objects.
Is there a way in spring-mongo to achieve this? Or is there any other frameworks on the same lines
You could use Spring Data to do that, just use the BasicQuery class instead of Query class. Your code will look like the following:
/* Any arbitrary string that could to parsed to DBObject */
Query q = new BasicQuery("{ filter : true }");
List<Entity> entities = this.template.find(q, Entity.class);
If you want more details:
http://static.springsource.org/spring-data/data-mongo/docs/current/reference/html/#mongo.query
http://static.springsource.org/spring-data/data-mongodb/docs/current/api/org/springframework/data/mongodb/core/query/BasicQuery.html
Well I got to find this one in the Spring data MongoOperations...
String jsonCommand = "{username: 'mickey'}";
MongoOperations mongoOps = //get mongooperations implemantation
mongoOps.executeCommand(jsonCommand)
It returns an instance of CommandResult that encapsulates the result.
I am using the Play! framework along with Anorm to access the database. I often see examples like the following where object members are injected into the SQL statement directly.
My question is, are these inputs sanitized? Most examples look like the following:
object Person {
def save(p:Person) {
DB.withConnection ("default") { implicit connection =>
SQL("""
INSERT INTO person(firstName,lastName)
values ({firstName}, {lastName})
"""
).on(
"firstName" -> p.firstName,
"lastName" -> p.lastName
).executeUpdate()
}
}
}
I will attempt to find out by way of hacking, but it's easy to make a mistake so I thought asking was more appropriate, and I can draw on the wisdom of the crowd.
According to its source code, Anorm builds onlyjava.sql.PreparedStatements, which prevent such SQL injection. (see the PreparedStatement wikipedia page for a general explanation)