Finding associated mybatis query - java

To initiate a query I use :
org.apache.ibatis.session.SqlSession.seleteList("myquery");
myquery itself is defined within an XML configuration file.
With Spring JDBC as the query statements is defined with the class itself it is very easy find the query associated with a given method call. But with mybatis once I reach the query call I have to search for the argument (in this case "myquery") to discover where the actual query is defined.
Is there an easier method of finding a query associated with a method call instead of manually searching for references ? I'm thinking there isn't as since the query itself is within an XML file not a .java file and IDE maintains a "linking" of methods, constants etc between the files.

There are two ways to do that but you will need to use mapper interfaces.
The first approach is to use IDE plugin. There are several plugins for IntelliJ and some for eclipse. Plugin for IntelliJ says it has
Proxy interfaces support, "Go to Implementaion" jumps right into
mapper xml
Another way is to define queries using annotations. In this case queries will be directly in java file.
Define query in mapper interface
interface MyMapper {
#Select("Select * from myentity where id = #id")
MyEntity selectMyEntity(#Param("id") Long id);
}
And then use mapper like usually:
MyMapper mapper = session.getMapper(MyMapper.class);
MyEntity myEntity = mapper.selectMyEntity(101);

Related

JpaSpecificationExecutor, how to change the field in SELECT

dears.
Currently, I am working with JpaSpecificationExecutor API, cause I need to create dynamic queries based on a lot of optional search criteria, for this I am starting with a root entity, which is included in the generic type in the JpaSpecificationExecutor interface.
The code to make the build in the Specification (which is included in the findAll method that belongs to repository interface) is the following:
public Specification<T> build(){
return (root, query, criteriaBuilder) -> {
Predicate filters = null;
//createPredicate is a method to create predicates (it does not matter in this code)
filters = createPredicate(root, criteriaBuilder, searchCriterias);
return filters;
};
}
Now each is working fine, but there is a little detail, in the query I am using joins to make relation with other entities, but when I get the response, like in this code:
List<EXAMPLE> examples = repository.findAll(filters.build());
I am not able to see the filter data in other entities, just I can see the field in the root entity (It is EXAMPLE entity) because these ones are appearing in the query formed. so, I would like to include in the SELECT the other entities, in order to see the filter data by means of the JOINs, but until now I have not been able to do it.
I have seen in any inputs, that I can use these codes in my build code, I have tried, but the new files are not appearing in the generated query:
query.select, or query.multiselect
Ref:
Ref. 1
Also, I have found that this is not working with JpaSpecificationExecutor, because the list of attributes in the SELECT is assigned by the entity Ref. 2
My question is, does someone know if exists another way to change the field in the SELECT with JpaSpecificationExecutor.
Regards.

Spring Repository without #Query

I am working on a desktop application built using spring framework and one of the part of the application is not working. I found that the repository class does not have any queries with #Query annotation. I haven't encountered it before.
When I try to open the form that uses this, I get an error that the application is not able to connect to the database. The application has 3 databases specified in the application.properties. I have the following questions:
1) How does the following code work without a query specified with #Query annotation. Or where is the query written.
#Repository
public interface AccountRepository extends JpaRepository<Account, Long> {
List<Account> findAccountsByActiveIsTrueAndAccountTypeEquals(String accountType);
List<Account> findAccountsByAccountTypeLike(String type);
}
2) How do we specify which of the database to search for. For example: I have 3 mysql databases currently connected to my application. I wish to access data from DB1 through my Spring boot application through the usual flow of
UI model-> BE Controller/ Service layer -> Repository(Interface) which (usually) has the query written with #Query. How we specify which database this query goes for ?
For your first question I can answer that the JpaRepository has an internal system that analyses the method name you have written and then generates the query that has to be executed to the database.
The #Query annotation is used when the method name and the generated query is not returning the result you wanted to so you specifically tell the compiler which query should be executed.
As mentioned here: https://docs.spring.io/spring-data/jpa/docs/1.5.0.RELEASE/reference/html/jpa.repositories.html
2.3.1 Query lookup strategies.
The JPA module supports defining a query manually as String or have it being derived from the method name.
Declared queries
Although getting a query derived from the method name is quite convenient, one might face the situation in which either the method name parser does not support the keyword one wants to use or the method name would get unnecessarily ugly. So you can either use JPA named queries through a naming convention (see Section 2.3.3, “Using JPA NamedQueries” for more information) or rather annotate your query method with #Query (see Section 2.3.4, “Using #Query” for details).
So basically using a naming convention will do the magic.
Also an interesting question and perfect answer can be found here:
How are Spring Data repositories actually implemented?
For your second question you can refer to this example:
https://www.baeldung.com/spring-data-jpa-multiple-databases
It might be a bit complicated in the beginning but eventually it will work.
He use JPA, JpaRepository has CRUD methodes
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#reference
In your application.properties, you can put your mysql DB info
Why this works without #Query?
Because you are using JpaRepository which provides an easy way to get data based on your entity and it's fields.
Here your Account will have active, accountType etc fields. You can use JPA's query creation keywords such as AND, OR, Equals, Like and many more.
Derived queries with the predicates IsStartingWith, StartingWith, StartsWith, IsEndingWith", EndingWith, EndsWith, IsNotContaining, NotContaining, NotContains, IsContaining, Containing, Contains the respective arguments for these queries will get sanitized. This means if the arguments actually contain characters recognized by LIKE as wildcards these will get escaped so they match only as literals. The escape character used can be configured by setting the escapeCharacter of the #EnableJpaRepositories annotation.
How do we specify which of the database to search?
You can create configuration classes based on your databases and define data sources based on that using #PropertySource.
For more details see example here
#Configuration
#PropertySource({ "classpath:persistence-multiple-db.properties" })
#EnableJpaRepositories(
basePackages = "com.baeldung.multipledb.dao.product",
entityManagerFactoryRef = "productEntityManager",
transactionManagerRef = "productTransactionManager"
)

How to make dynamic queries at run-time in Spring Boot and Data?

I am new to Java and started with Spring Boot and Spring Data JPA, so I know 2 ways on how to fetch data:
by Repository layer, with Literal method naming: FindOneByCity(String city);
by custom repo, with #Query annotation: #Query('select * from table where city like ?');
Both ways are statical designed.
How should I do to get data of a query that I have to build at run time?
What I am trying to achieve is the possibility to create dynamic reports without touching the code. A table would have records of reports with names and SQl queries with default parameters like begin_date, end_date etc, but with a variety of bodies. Example:
"Sales report by payment method" | select * from sales where met_pay = %pay_method% and date is between %begin_date% and %end_date%;
The Criteria API is mainly designed for that.
It provides an alternative way to define JPA queries.
With it you could build dynamic queries according to data provided at runtime.
To use it, you will need to create a custom repository implementation ant not only an interface.
You will indeed need to inject an EntityManager to create needed objects to create and execute the CriteriaQuery.
You will of course have to write boiler plate code to build the query and execute it.
This section explains how to create a custom repository with Spring Boot.
About your edit :
What I am trying to achieve is the possibility to create dynamic
reports without touching the code. A table would have records of
reports with names and SQl queries with default parameters like
begin_date, end_date etc, but with a variety of bodies.
If the queries are written at the hand in a plain text file, Criteria will not be the best choice as JPQL/SQL query and Criteria query are really not written in the same way.
In the Java code, mapping the JPQL/SQL queries defined in a plain text file to a Map<String, String> structure would be more adapted.
But I have some doubts on the feasibility of what you want to do.
Queries may have specific parameters, for some cases, you would not other choice than modifying the code. Specificities in parameters will do query maintainability very hard and error prone. Personally, I would implement the need by allowing the client to select for each field if a condition should be applied.
Then from the implementation side, I would use this user information to build my CriteriaQuery.
And there Criteria will do an excellent job : less code duplication, more adaptability for the query building and in addition more type-checks at compile type.
Spring-data repositories use EntityManager beneath. Repository classes are just another layer for the user not to worry about the details. But if a user wants to get his hands dirty, then of course spring wouldn't mind.
That is when you can use EntityManager directly.
Let us assume you have a Repository Class like AbcRepository
interface AbcRepository extends JpaRepository<Abc, String> {
}
You can create a custom repository like
interface CustomizedAbcRepository {
void someCustomMethod(User user);
}
The implementation class looks like
class CustomizedAbcRepositoryImpl implements CustomizedAbcRepository {
#Autowired
EntityManager entityManager;
public void someCustomMethod(User user) {
// You can build your custom query using Criteria or Criteria Builder
// and then use that in entityManager methods
}
}
Just a word of caution, the naming of the Customized interface and Customized implementating class is very important
In last versions of Spring Data was added ability to use JPA Criteria API. For more information see blog post https://jverhoelen.github.io/spring-data-queries-jpa-criteria-api/ .

How to configure JOOQ to codegen tables with the same structure?

I have some legacy tables with the same structure in MySQL like:
my_table_01
my_table_02
my_table_03
...
Is there a way I can configure JOOQ codegen to generate only one table/record class which shared by all those tables ?
There are two steps that you have to do in order to achieve what you like to do:
1. Configure the code generator
You'll probably have to exclude my_table_02 and my_table_03 from being generated. You can do this by specifying the <excludes/> tag as documented here.
Optionally, you could use generator strategies (programmatic config) or matcher strategies (XML config) to rename my_table_01 to my_table.
2. Configure your runtime
While running queries against MY_TABLE, you can specify runtime table mapping in order to map MY_TABLE back to my_table_01 or my_table_02 or my_table_03. This mapping works on a per-configuration basis, i.e. it will have the scope of a single query if you're using one configuration per query.
Another option is, of course, to abstract over these suffixes in your client code, e.g. via a table selection method:
public static Table<?> myTable() {
if (something)
return DSL.table("{0}_01", MY_TABLE);
else if (somethingElse)
return DSL.table("{0}_02", MY_TABLE);
...
}

How Can I Query a DB for ResultSet which is not Mapped into an Entity(JPA, JBoss)

I'm running an application in JBoss and Using JPA.
For a report I need a group by query which I expect to return a result set with the following structure example:
count,idA,idB
I did not find a way to implement this in JPA.
What are my best options for implementing this considering I'm developing in JBoss 5, EJB3
You can use a custom holder class and use the NEW keyword in your query:
SELECT NEW com.mycompany.myapp.MyClass(count, idA, idB)
FROM ...
WHERE ...
Of course, MyClass needs to have the proper constructor defined.
In the case of Native queries, you can create a dummy entity into which the result set can be mapped to (Native query will not be mapped into an Object unless its a real managed entity).
The entity is a dummy as it will not be persisted and it only used for mapping the result set of the native query into this entity.

Categories