How to setup concurrent calls in Oracle 10g Java VM - java

If somebody can explain me how to properly configure plsql java wrapper when different database users invoke same procedure to ensure correct concurrent resource access handling.
DBMS and JAVA: Oracle 10g, internal JavaVM 1.4.2
I have MyDatabse with 1 shema owner and 10 db users granted to connect to it:
DBOWNER
DBUSER01
DBUSER02
...
DBUSER10
I have PL/SQL wrapper procedure:
my_package.getUser() that wrapps UserHandler.getUser()
I have java class UserHandler uploaded to MyDatabase with loadjava:
public class UserHandler {
private static final int MAX_USER_COUNT = 10;
private static final String USERNAME_TEMPLATE = "EIS_ORA_20";
private static int currentUserSeed = 0;
/**
* Generates EIS user according to pattern agreed by EIS developers. It
* circles user pool with round-robin method ensuring concurrent calls.
*
* #return valid EIS USERNAME
*/
synchronized public static String getUser() {
String newUser = USERNAME_TEMPLATE + currentUserSeed;
currentUserSeed++;
currentUserSeed = currentUserSeed % MAX_USER_COUNT;
return newUser;
}
}
The idea of wrapper is to ensure proper distribution of external information system usernames to DBUSERS connected to MyDatabase with Oracle Forms Client Application.
My problem is that when 5 users concurently call procedure my_package.getUser() I got:
DBUSER01 - call to my_package.getUser() returned EIS_ORA_200
DBUSER02 - call to my_package.getUser() returned EIS_ORA_200
DBUSER03 - call to my_package.getUser() returned EIS_ORA_200
DBUSER04 - call to my_package.getUser() returned EIS_ORA_200
DBUSER05 - call to my_package.getUser() returned EIS_ORA_200
I was expected that each DBUSER would get different user (as I confirmed in my JUnit tests where multiple concurrent threads invoke UserHandler.getUser()).
Later I've red that plsql wrapper calls can be setup in 2 maner:
to share java memory space between DBUSERS or
to separate memory space for each DBUSER
My conclusion is that UserHandler class is loaded for each DBUSER separately and that is why I have no use of static counter and synchronized method.
How to configure MyDatabase to force calls to my_package.getUser() use same java space for each DBUSER?
Thank you very much!

I don't believe there is any way to configure Oracle to share a JVM between multiple user sessions. The Java Developer's Guide for 10g states:
Oracle JVM model
Even when thousands of users connect
to the server and run the same Java
code, each user experiences it as if
he is running his own Java code on his
own JVM...
Generally the appropriate way to share data between sessions in an RDBMS is with database objects. In this case the simplest thing would be to use an Oracle sequence, with minvalue 1, maxvalue 10, and cycling enabled. You could just select from the sequence directly in the Java code.
Another approach would be to simply generate a uniformly-distributed random number between 1 and 10. If there are enough sessions then over time this should distribute the sessions evenly.

Related

What does this methods do?

I'm new to connecting Java to SQL Server but hopefully I manage to connect them successfully through helps of various tutorials. But there are these methods and syntax that I couldn't explain for myself.
1.
Connection conn=DriverManager.getConnection("jdbc:sqlserver://localhost:1433;databaseName=login_DB;integratedSecurity=true");
Regarding the code above, what does integratedSecurity=true do?
2.
String user = rss.getString(1);
String pass = rss.getString(2);
Does the parameter inside getString(1) and getString(2) pertains to the column in the Database? And also, how does the ResultSet affects the getString()?
3.
while(rss.next()){
String user = rss.getString(1);
String pass = rss.getString(2);
if(usernameTF.getText().trim().equals(user)&&passwordTF.getText().trim().equals( pass)){
count = 1;
}//if success
}//while
Lastly, at least for now, does the while(rss.next()) method simply means that while there is a row in my table?
I know my code is a bad practice. But I am really trying my best to make it better.
Integrated Security = true/SSPI : the current Windows account credentials are used for authentication.
Integrated Security = False : User ID and Password are specified in the connection String.
rs.getString(1) - get 1 return column from your select statement.
Select x,y,z from table; rs.getString(1) gives x column result for particular row.
Your query returning n number row ,each time rs.next() check is there row available after current row.
Difference between Integrated Security = True and Integrated Security = SSPI
Yes the number refers to the column number, or you can pass a String as the column name to pull data.
Yes, whilst there is data in your ResultSet, for each iteration it will move the cursor to the next row of data available. Where you can access columns specifically using the syntax from part 2 of your question.
Hope this is useful.
According to Microsoft they are the same thing.
When false, User ID and Password are specified in the connection. When true, the current Windows account credentials are used for authentication.
Recognized values are true, false, yes, no, and sspi (strongly recommended), which is equivalent to true.
There however is a difference between them according to the comment below:
True ignores User Id and Password if provided and uses those of the running process, SSPI it will use them if provided which is why MS prefers this.
They are equivalent in that they use the same security mechanism to authenticate but that is it.
refer this link...!

Java- read data from voltdb with native procedure

I'm trying to read data from a VoltDB database with Java. Now, it can be done using result sets from SQL statements, but there should (I'm told) be another way of doing it, native to VoltDB, similarly to how data is written to a VoltDB database (with client.callProcedure). I can't figure out how to do that; it seems like it should be a pretty simple thing to do, but I don't see any simple way to do it in client.
Yes, if you are using client.callProcedure for your writes, you can certainly use the same API for your reads. Here is a simple example:
ClientResponse cr = client.callProcedure(procname,parameters);
VoltTable[] tables = cr.getResults();
VoltTable table_a = tables[0];
while (table_a.advanceRow()) {
System.out.println("Column 0 is " + table_a.getString(0));
}
Here is a shortened example:
VoltTable table_a = client.callProcedure(procname,parameters).getResults()[0];
while (table_a.advanceRow()) {
System.out.println("Column 0 is " + table_a.getString(0));
}
Rather than procname and parameters, you could also call AdHoc SQL like this:
VoltTable table_a = client.callProcedure("#AdHoc","SELECT * FROM helloworld;").getResults()[0];
These examples above are synchronous or blocking calls. If you want your application to use asynchronous calls, you can also use a Callback object with the call, so the client would continue executing subsequent code. When the response is received by the client thread that handles callbacks, the result could be passed off to another thread in our application to read the results.
You can read more about the API in the Java Client API Javadoc.
If you want to use client.callProcedure function. You have to make that procedure in VoltDB's user interface . For example,
CREATE PROCEDURE insertNumber AS
INSERT INTO NUMBERS (number1) values (1)
this will create a procedure. When you call it with client.callProcedure(insertNumber), that will do the work.

JDBCTemplate returns data when debugging but not during normal operation

Inside a web application, Spring's JdbcTemplate returns an empty list for some simple sql (SELECT * FROM view_name -- view_name is a view of one column) where there is known data.
When I use the remote java application debugger with eclipse/tomcat, the query returns the results as expected.
Java Call
List<String> results = new ArrayList<String>();
results = jdbcTemplate.queryForList("select * from view_name", String.class)
I enabled Spring's jdbc logging (level DEBUG) and there is no difference in the output between debugging or normal runs other than results don't return with normal operation. I'm looking for any sort of pointers or other debugging tips to solve this issue.
The simple solution was to add a semi-colon to the query (e.g. select * from view_name;). I'm guessing that this idiosyncracy is more a function of PostGRES than Spring.
Are you running this query using a testcase, and when you normally run through the server you are getting the results?
If that is the case , then I think you need to look for the DataSource configuration for the connection pools.
But this is the first time hearing the issue, checking your data source configuration might help.

Hibernate Batch Processing Using Native SQL

I have an application using hibernate. One of its modules calls a native SQL (StoredProc) in batch process. Roughly what it does is that every time it writes a file it updates a field in the database. Right now I am not sure how many files would need to be written as it is dependent on the number of transactions per day so it could be zero to a million.
If I use this code snippet in while loop will I have any problems?
#Transactional
public void test()
{
//The for loop represents a list of records that needs to be processed.
for (int i = 0; i < 1000000; i++ )
{
//Process the records and write the information into a file.
...
//Update a field(s) in the database using a stored procedure based on the processed information.
updateField(String.valueOf(i));
}
}
#Transactional(propagation=propagation.MANDATORY)
public void updateField(String value)
{
Session session = getSession();
SQLQuery sqlQuery = session.createSQLQuery("exec spUpdate :value");
sqlQuery.setParameter("value", value);
sqlQuery.executeUpdate();
}
Will I need any other configurations for my data source and transaction manager?
Will I need to set hibernate.jdbc.batch_size and hibernate.cache.use_second_level_cache?
Will I need to use session flush and clear for this? The samples in the hibernate tutorial is using POJO's and not native sql so I am not sure if it is also applicable.
Please note another part of the application is already using hibernate so as much as possible I would like to stick to using hibernate.
Thank you for your time and I am hoping for your quick response. If it is also possible could code snippet would really be useful for me.
Application Work Flow
1) Query Database for the transaction information. (Transaction date, Type of account, currency, etc..)
2) For each account process transaction information. (Discounts, Current Balance, etc..)
3) Write the transaction information and processed information to a file.
4) Update a database field based on the process information
5) Go back to step 2 while their are still accounts. (Assuming that no exception are thrown)
The code snippet will open and close the session for each iteration, which definitely not a good practice.
Is it possible, you have a job which checks how many new files added in the folder?
The job should run say every 15/25 minutes, checking how much files are changed/added in last 15/25 minutes and updates the database in batch.
Something like that will lower down the number of open/close session connections. It should be much faster than this.

IBM Websphere Command Cache Invalidation

My business flow is following:
Invalidate a command
Fetch data from command (database operations, little slower)
Step2 would be access by many concurrent users.
Now, when a command in invalidated, and user tries to fetch the data, multiple database queries starts executing because execute is little slower.
Is there any way to stop this multiple executions of queries?
In other words, the question is: Can we make the execution of command,
and fetching data from command as Synchronized?
Yes, you can do something like this.
public class Fetcher {
private static String data;
private long timestamp;
public synchronized String fetchData() {
String result="";
if (data!=null) {
result=data;
// let's invalidate too old data
if (new Date().getTime()-timestamp> 100000)
data=null;
} else {
DAO db = DAO.getConnection();
data = db.performQuery();
result=data;
}
return result;
}
}
If you are using a Dynacache cacheable command and the queries are the same for users, then the command should get cached after the first execution.
Only the first execution should hit the database, after that the data should be fetched from cache until the cache is invalidated.
I usually use Dynacache as part of IBM Websphere Commerce suite.
Websphere Commerce uses a scheduled command to check a table called CACHEIVL.
You would setup triggers which would insert an invalidation id into CACHEIVL when the target table is changed.
Since you don't have the scheduled Dynacache command you can implement something specific to your use case using Websphere schedulers,
Here is an example of a cacheable command using Dynacache.

Categories