Refresh an Oracle Materialized view in a Spring Data Repository - oracle

I need to refresh a materialized view in an Oracle database before I query the Spring Data Repository. I'm attempting to do this via a function in the Repository with a native query, like the following.
#Query("BEGIN DBMS_SNAPSHOT.REFRESH('MY_VIEW', 'C'); END;", nativeQuery = true)
fun refreshMaterializedView()
However, I am getting java.lang.NegativeArraySizeException when calling this method, although it works fine when being run directly on the database. What am I doing wrong here? Is there an alternative way to force the materialized view to refresh?

You need to annotate your method with #Modifying. It is really intended for DML statements but works for this as well.
#Modifying
#Query("BEGIN DBMS_SNAPSHOT.REFRESH('MY_VIEW', 'C'); END;", nativeQuery = true)
fun refreshMaterializedView()

Related

Spring boot #Query ignores #Table on view call

I have a spring boot 2 application that works great with entities that are mapped to a table that is in a MariaDB. I now do a view call and I have mapped that entity to the view using the #Table(name="ViewExpiredAccounts") annotation and now when the method is called the table name is ignored. I have a JpaRepository with this method:
#Query(value = "SELECT v FROM ViewExpiredAccounts v")
List<ViewExpiredAccount> expiredAccounts();
When I call this method I get an error:
Table 'view_expired_accounts' doesn't exist
The query SHOULD! translate the table name so that the eventual SQL query sent to MariaDB is: SELECT * from ViewExpiredAccount however it doesnt do that. Is this a bug in Spring??
did you reset the hibernate naming strategy?
if yes, the following property might help
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

Spring Boot ManyToMany Hibernate Persistance Performance

The question I have is probably a newbie one, however couldn't find the answer for that.
Why we use
User usr = entityManager.getReference(User.class, userId);
usr.getRoomsFavourites().add(entityManager.getReference(Room.class, roomId));
entityManager.persist(usr);
Instead of directly insert into a relational table?
#Query(value = "INSERT INTO user_room_favourites (user_id, room_id) VALUES (?1, ?2)", nativeQuery = true)
void addFavoriteRoomByUserId(Long userId, Long roomId);
For the first option, we have a lot of overhead, even getReference only get the ID of Entity, it will go to the database, and in my case, it will make 3 large selects with a lot of joins before actually insert
For the second option, we only make the insertion
The only disadvantages I can see here are errors like user or room didn't exist or duplicate PK:
could not execute statement; SQL [n/a]; constraint [user_room_favourites_pkey];
But the exceptions can easily be handled.
Also, the migration for another database in the future can be more difficult because of Native Query.
I can not see any other disadvantage and I think for performance purposes the second way is much better.
Can someone explain this?
Thanks in advance.

Custom query within JPA server-managed session

I'm trying to execute an unrelated query (other_table) within a JTA session (server-managed) in order to do some validations, before persisting the bean EJB into DB with JPA.
Here is what I want to do (aprox):
#PersistenceUnit(unitName="DynamicDatabase")
EntityManagerFactory emf;
#TransactionAttribute(TransactionAttributeType.REQUIRED)
private long nextEntryid() {
em = emf.createEntityManager();
Query query = em.createQuery("select t from OTHER_TABLE t");
// do some validation and checking
MyTable bean = new MyTable();
em.persist(bean);
}
However I keep getting a server error, it does not allow to interact with other database items that are not persisted:
org.apache.openjpa.persistence.ArgumentException:
An error occurred while parsing the query filter (query): The name "OTHER_TABLE" is not a recognized entity (...) Perhaps you meant MyTable, which is a close match.
<persistence-unit name="DynamicDatabase" transaction-type="JTA">
<jta-data-source>jdbc/DB2DynamicConnection</jta-data-source>
<class>jorge.java.dynamicdatabase.db.MyTable</class>
</properties>
</persistence-unit>
The question is: what is the proper way to query/alter another table within the same JPA DB connection and JTA transaction?
Pretty newby about this, please be patient with me. Been working on this very long.
Edit: I don't think it's related but FYI I'm using WebSphere Liberty Profile 8.5.5.4, JSDK 8u31, EclipseEE Luna 4.4.2 for Web Dev. Going to add it to tags.
The problem is that you have a #NamedQuery that references the entity OTHER_TABLE, and that does not exist or not marked as being an Entity (try in both Java class and persistence.xml).
If the OtherTable Java class is not an entity and if it MUST remain so, then you could use Constructors in JPQL-queries:
SELECT NEW com.domain.reports.MyReport(u.firstName, u.lastName, u.birthday) FROM User u
If you need to write plain SQL queries, then you could do it using native queries, as they are known in the JPA specification.
Based on Andrei's suggestion, the JPQL (Java Persistence Query Language) operates on objects, not on tables. This means that em.createQuery() can't be used for universal database interaction.
To execute any SQL statement generally speaking (inside the container-managed transaction JTA), it is necessary to get the DB connection from the entity manager (it will return the persistence context unit JPA).
// Get container's objects
em = emf.createEntityManager();
java.sql.Connection conn = em.unwrap(java.sql.Connection.class);
// Run the query
Statement sql = conn.createStatement();
ResultSet rs = sql.executeQuery("select * from OTHER_TABLE");
rs.next()
(...)
//Container-managed connection shouldn't be closed.
rs.close;
sql.close;
Notice that unwrap call works for JPA but not for Hibernate (other questions already exist on this point). Notice the different language used for the SQL statement select * from than a named query JPQL select t from. Exception handling must be also controlled as usual with a } finally { clause.
That way would allow to execute a complex custom statement within server-managed transaction without using JAVA entities and I can finally sleep.

How to use table functions in queries with Spring Data

When using Spring Data JPA with Hibernate, what are the options available to write queries that join with table functions.
For example, I'd like to generate queries as described below:
CASE 1: SELECT * FROM getfoo(1) AS t1;
CASE 2: SELECT * FROM getfoo(1) x INNER JOIN tbl1 y on x.id = y.id;
Edit
To elaborate more, I'm using Spring Data for all things CRUD (It works great). However, I need to write complicated queries that join tables with "table functions". Table functions(AKA Table-Valued User-Defined Functions) are database functions that return tabled-values which can be used in the JOIN clause in combination with tables. Postgresql and Sql Server support them.
In the Spring Data realm, which includes much more than JPA, what are the options to consider when writing such queries? Whats the best practice from your experience? user2658013 was kind enough to describe one such approach using the entityManager.reateNativeQuery method.
In my mind here are the options:
JPA
Use #NamedStoredProcedureQuery ( >=JPA 2.1)
Use entityManager.createNativeQuery or #NamedNativeQuery
Non-standard
Use Spring Data's #Query to declare finder queries directly on repository methods.
Use SimpleJdbcCall
Any others?
I believe you are asking about Postgres stored functions. Postgres stored functions are analogous to "Stored Procedures". So I think you are asking how would invoke a stored procedure using JPA? Am I close?
The following pseudo code is derived from details published here (see section on Stored Procures):
http://www.oracle.com/technetwork/articles/vasiliev-jpql-087123.html
EntityManager em = emf.createEntityManager();
SOMEVAL_TYPE result = (SOMEVAL_TYPE)em.createNativeQuery("SELECT getfoo(?1) FROM SOMEDB")
.setParameter(1, SOME_PARM)
.getSingleResult();
In general you can use JPQL with JPA instead of SQL.
Note! The above assumes you have already created the stored function in you Postgres database.
Hope that helps :)

How to read changed values with native query during one transaction? (Spring and JPA)

We have container transaction with Spring and JPA (Hibernate). I need to make an update on a table to "flag" some rows via native statements. Then we insert some rows via EntityManager from JPATemplate to this table. After that, we need to calculate changes in the table via native statement (with Oracle's union and minus, complex groups...)
I see that changes from step 1 and 2 are not commited and thats why the statement from 3 fails. I already tried with transaction propagation REQUIRES_NEW, EntityManager.flush... Didn't work.
1) update SOMETABLE acolumn = somevalue (native)
2) persist some values into SOMETABLE (via entity manager)
3) select values from SOMETABLE
Is there a possibility to read the changes from step 1 and 2 in step 3?
I guess you are using the same DataSource in the JpaTransactionManager, JdbcTemplate and JpaTemplate and have enabled #Transactional with this:
<tx:annotation-driven />
Assuming it is not a configuration bug, my best guess is that you're calling on the #Transactional method from a method in the same class?
In that case, you need AspectJ to weave in the transaction logic or refactor the code so the #Transactional method is in another class than the calling method. (The refactor option is the easy and preferred one)
If this doesn't solve your problem, you should add the relevant classes to your question together with relevant log messages.

Resources