Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
You heard it right.
I am currently a Master's student at KU Leuven for Information Management programme and for our Database Management assignment, we have been asked to write an app that will make use of JDBC.
I have installed MySQL, MySQL Workbench and Eclipse without any problems and we are provided with the database and some kind of a template to work with.
The assignment is:
The app asks a customer what s/he would like to do.
If s/he would like to place a new order, s/he chooses option ‘1’. The program >asks the customer for her/his customer ID (only input existing customer ID’s >from the customer table). Next, the program outputs a list of products (id, >name, category), and asks the customer which product s/he wants to order. This >list needs to be ordered alphabetically by category and then by product name. >The program then outputs the restaurant that has the best rating for this >product (product name, restaurant name and rating). Additionally, it registers >the order in the correct database table.
If a customer wants to see a list of product categories that have been ordered >at least 5 times, s/he chooses option ‘2’. A list of food category names >together with the number of orders is displayed, which is sorted by a >decreasing number of orders.
If a customer wants to see the top 5 of most sold products, s/he chooses option >‘3’. The program shows a list of 5 products, together with the number of orders >(product ID, product name, number of orders), which is sorted by a dreasing >number of orders.
This is repeated until the user enters a ‘0’. In that case, the program should >display the message ‘END OF SESSION’.
The sample code we are provided with is:
package connectionMySql;
import java.sql.*;
import java.io.*;
public class connectionMySql {
/**
* #author X X
*
*/
static {
try {
/* Type 4 Driver */
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println("Could not load MySql driver.");
System.err.println(e.getMessage());
System.exit(1);
}
}
public static void main(String args[]) {
String uname = null;
String psswrd = null;
Integer choice = 1;
/* Location of the database */
String host = "jdbc:mysql://localhost/orderdb";
/* Sample query */
String query = "SELECT * FROM restaurant";
/* Reading log-in data (username and password) */
try {
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter your username on MySql: ");
uname = br1.readLine();
BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter your password on MySql: ");
psswrd = br2.readLine();
} catch (IOException e) {
System.out.print("Failed to get uname/passwd");
System.out.println(":" + e.getMessage());
System.exit(1);
}
/* Example of querying a database */
try {
/* Connect to MySql database */
Connection conn = DriverManager.getConnection(host, uname, psswrd);
System.out.println("Connection established...");
System.out.println();
/* Create statement */
Statement stmt = conn.createStatement();
/* Execute the query */
ResultSet rs = stmt.executeQuery(query);
/* Output */
System.out.println("This is an example how you query a DBMS.");
System.out.println();
System.out.println(query);
System.out.println("ID // First Name // Last Name");
System.out.println("------------------------------");
while (rs.next()) {
System.out.print(rs.getString(1));
System.out.print((" // "));
System.out.print(rs.getString(2));
System.out.print((" // "));
System.out.print(rs.getString(3));
System.out.print((" // "));
System.out.println(rs.getString(4));
}
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
System.out.println("SQL Exception: ");
System.err.println(e.getMessage());
}
/* Example of choice options */
while (choice != 0) {
/*Ask for user's choice*/
try {
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
System.out.println();
System.out.println("This is an example of a choice menu.");
System.out.println();
System.out.println("Please choose between the following options:");
System.out.println(" (1) Add registration");
System.out.println(" (2) Show popular sessions list");
System.out.println(" (0) Quit");
System.out.print("Enter your choice: ");
choice = Integer.parseInt(br1.readLine());
} catch (NumberFormatException ex) {
System.err.println("Not a valid number");
} catch (IOException e) {
e.printStackTrace();
}
if (choice == 1) {
/* TODO */
} else if (choice == 2) {
/* TODO */
} else {
/* TODO */
}
}
System.out.println();
System.out.println("End of Session");
}
}
I want to learn new things. That's why I am here however I do not come from an IT background and this much of assumption that I could do all this without problems is not realistic at all.
I do not have a hint if I am expected to do SQL queries (which I am a bit familiar with) or JDBC coding (which I do not know at all) to get what I want. Plus, I don't have any idea of how Java works, what classes are etc.
I am not looking for copy-pasteable shortcuts, I want guidance, something to start with. I am so frustrated right now.
If you've never written Java before I'd say you're going to have a big problem.
JDBC and relational databases are not "Hello World".
You're working on a Masters degree. You don't say what your undergraduate degree is, but let's assume that you can program.
The best place to start is the JDBC tutorial from Oracle/Sun.
One comment: The code you posted is horrible. The style is poor and it's hard to read. I'd give the professor that handed out such a mess a failing grade.
Here's a recommendation: Big problems are easier to solve if you break them up into smaller ones. Decomposition is a core skill in computer science.
I'd recommend that you not put everything in a main method. Decompose discrete operations into separate methods that you can code and test independently.
It's never too early to learn about JUnit. You will find this far less painful if you write a method, test it, and move onto the next.
Relational databases all do the same thing: CRUD operations (Create/Read/Update/Delete). You can start with a generic interface:
package persistence;
public interface DataAccess<K, V> {
List<V> findAll();
V find(K key);
K save(V value);
void update(K key, V value);
void delete(K key);
}
Related
What Happened
All the data from last month was corrupted due to a bug in the system. So we have to delete and re-input these records manually. Basically, I want to delete all the rows inserted during a certain period of time. However, I found it difficult to scan and delete millions of rows in HBase.
Possible Solutions
I found two way to bulk delete:
The first one is to set a TTL, so that all the outdated record would be deleted automatically by the system. But I want to keep the records inserted before last month, so this solution does not work for me.
The second option is to write a client using the Java API:
public static void deleteTimeRange(String tableName, Long minTime, Long maxTime) {
Table table = null;
Connection connection = null;
try {
Scan scan = new Scan();
scan.setTimeRange(minTime, maxTime);
connection = HBaseOperator.getHbaseConnection();
table = connection.getTable(TableName.valueOf(tableName));
ResultScanner rs = table.getScanner(scan);
List<Delete> list = getDeleteList(rs);
if (list.size() > 0) {
table.delete(list);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != table) {
try {
table.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static List<Delete> getDeleteList(ResultScanner rs) {
List<Delete> list = new ArrayList<>();
try {
for (Result r : rs) {
Delete d = new Delete(r.getRow());
list.add(d);
}
} finally {
rs.close();
}
return list;
}
But in this approach, all the records are stored in ResultScanner rs, so the heap size would be huge. And if the program crushes, it has to start from the beginning.
So, is there a better way to achieve the goal?
Don't know how many 'millions' you are dealing with in your table, but the simples thing is to not try to put them all into a List at once but to do it in more manageable steps by using the .next(n) function. Something like this:
for (Result row : rs.next(numRows))
{
Delete del = new Delete(row.getRow());
...
}
This way, you can control how many rows get returned from the server via a single RPC through the numRows parameter. Make sure it's large enough so as not to make too many round-trips to the server, but at the same time not too large to kill your heap. You can also use the BufferedMutator to operate on multiple Deletes at once.
Hope this helps.
I would suggest two improvements:
Use BufferedMutator to batch your deletes, it does exactly what you need – keeps internal buffer of mutations and flushes it to HBase when buffer fills up, so you do not have to worry about keeping your own list, sizing and flushing it.
Improve your scan:
Use KeyOnlyFilter – since you do not need the values, no need to retrieve them
use scan.setCacheBlocks(false) - since you do a full-table scan, caching all blocks on the region server does not make much sense
tune scan.setCaching(N) and scan.setBatch(N) – the N will depend on the size of your keys, you should keep a balance between caching more and memory it will require; but since you only transfer keys, the N could be quite large, I suppose.
Here's an updated version of your code:
public static void deleteTimeRange(String tableName, Long minTime, Long maxTime) {
try (Connection connection = HBaseOperator.getHbaseConnection();
final Table table = connection.getTable(TableName.valueOf(tableName));
final BufferedMutator mutator = connection.getBufferedMutator(TableName.valueOf(tableName))) {
Scan scan = new Scan();
scan.setTimeRange(minTime, maxTime);
scan.setFilter(new KeyOnlyFilter());
scan.setCaching(1000);
scan.setBatch(1000);
scan.setCacheBlocks(false);
try (ResultScanner rs = table.getScanner(scan)) {
for (Result result : rs) {
mutator.mutate(new Delete(result.getRow()));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
Note the use of "try with resource" – if you omit that, make sure to .close() mutator, rs, table, and connection.
This is my first time trying to read and write to a VSAM file. What I did was:
Created a Map for the File using VSE Navigator
Added the Java beans VSE Connector library to my eclipse Java project
Use the code show below to Write and Read to the KSDS file.
Reading the file is not a problem but when I tried to write to the file it only works if I go on the mainframe and close the File before running my java program but it locks the file for like an hour. You cannot open the file on the mainframe or do anything to it.
Anybody can help with this problem. Is there a special setting that I need to set up for the file on the mainframe ? Why do you first need to close the file on CICS to be able to write to it ? And why does it locks the file after writing to it ?
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.sql.*;
public class testVSAM {
public static void main(String argv[]){
Integer test = Integer.valueOf(2893);
String vsamCatalog = "VSESP.USER.CATALOG";
String FlightCluster = "FLIGHT.ORDERING.FLIGHTS";
String FlightMapName = "FLIGHT.TEST2.MAP";
try{
String ipAddr = "10.1.1.1";
String userID = "USER1";
String password = "PASSWORD";
java.sql.Connection jdbcCon;
java.sql.Driver jdbcDriver = (java.sql.Driver) Class.forName(
"com.ibm.vse.jdbc.VsamJdbcDriver").newInstance();
// Build the URL to use to connect
String url = "jdbc:vsam:"+ipAddr;
// Assign properties for the driver
java.util.Properties prop = new java.util.Properties();
prop.put("port", test);
prop.put("user", userID);
prop.put("password", password);
// Connect to the driver
jdbcCon = DriverManager.getConnection(url,prop);
try {
java.sql.PreparedStatement pstmt = jdbcCon.prepareStatement(
"INSERT INTO "+vsamCatalog+"\\"+FlightCluster+"\\"+FlightMapName+
" (RS_SERIAL1,RS_SERIAL2,RS_QTY1,RS_QTY2,RS_UPDATE,RS_UPTIME,RS_EMPNO,RS_PRINTFLAG,"+
"RS_PART_S,RS_PART_IN_A_P,RS_FILLER)"+" VALUES(?,?,?,?,?,?,?,?,?,?,?)");
//pstmt.setString(1, "12345678901234567890123003");
pstmt.setString(1, "1234567890");
pstmt.setString(2,"1234567890123");
pstmt.setInt(3,00);
pstmt.setInt(4,003);
pstmt.setString(5,"151209");
pstmt.setString(6, "094435");
pstmt.setString(7,"09932");
pstmt.setString(8,"P");
pstmt.setString(9,"Y");
pstmt.setString(10,"Y");
pstmt.setString(11," ");
// Execute the query
int num = pstmt.executeUpdate();
System.out.println(num);
pstmt.close();
}
catch (SQLException t)
{
System.out.println(t.toString());
}
try
{
// Get a statement
java.sql.Statement stmt = jdbcCon.createStatement();
// Execute the query ...
java.sql.ResultSet rs = stmt.executeQuery(
"SELECT * FROM "+vsamCatalog+"\\"+FlightCluster+"\\"+FlightMapName);
while (rs.next())
{
System.out.println(rs.getString("RS_SERIAL1") + " " + rs.getString("RS_SERIAL2")+ " " + rs.getString("RS_UPTIME")+ " " + rs.getString("RS_UPDATE"));
}
rs.close();
stmt.close();
}
catch (SQLException t)
{
}
}
catch (Exception e)
{
// do something appropriate with the exception, *at least*:
e.printStackTrace();
}
}
}
Note: the OS is z/VSE
The short answer to your original question is that KSDS VSAM is not a DBMS.
As you have discovered, you can define the VSAM file such that you can update it both from batch and from CICS, but as #BillWoodger points out, you must serialize your updates yourself.
Another approach would be to do all updates from the CICS region, and have your Java application send a REST or SOAP or MQ message to CICS to request its updates. This does require there be a CICS program to catch the requests from the Java application and perform the updates.
The IBM Mainframe under z/VSE has different partitions that run different jobs. For example partition F7 CICS, partition F8 Batch Jobs, ETC.
When you define a new VSAM file you have to set the SHAREOPTIONS of the file. When I define the file I set the SHAREOPTIONS (2 3). 2 Means that only one partition can write to the file.
So when the batch program (in a different partition to the CICS partition) which is called from Java was trying to write to the file it was not able to write to the file unless I close the file in CICS first.
To fix it I REDEFINE the CICS file with SHAREOPTIONS (4 3). 4 Means that multiple partitions of the Mainframe can write to it. Fixing the problem
Below is a part of the definition code where you set the SHAREOPTION:
* $$ JOB JNM=DEFFI,CLASS=9,DISP=D,PRI=9
* $$ LST CLASS=X,DISP=H,PRI=2,REMOTE=0,USER=JAVI
// JOB DEFFI
// EXEC IDCAMS,SIZE=AUTO
DEFINE CLUSTER -
( -
NAME (FLIGHT.ORDERING.FLIGHTS) -
RECORDS (2000 1000) -
INDEXED -
KEYS (26 0) -
RECORDSIZE (128 128) -
SHAREOPTIONS (4 3) -
VOLUMES (SYSWKE) -
) -
.
.
.
I am developing an Android app that needs to fetch data from a huge MS Access database of 120MB size.
I have written code to establish connectivity and execute a simple query on the database. I run the same java code on my laptop and my Android device.Here's the code:
p
ackage practiceDB;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
import java.util.Scanner;
import net.ucanaccess.converters.TypesMap.AccessType;
import net.ucanaccess.ext.FunctionType;
import net.ucanaccess.jdbc.UcanaccessConnection;
import net.ucanaccess.jdbc.UcanaccessDriver;
public class Example {
private Connection ucaConn;
public Example() {
try {
this.ucaConn = getUcanaccessConnection("VehicleDatabase2.mdb");
} catch (SQLException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws ClassNotFoundException, SQLException {
System.out.println("Please enter an int");
new Scanner(System.in).nextInt();
try {
Example example = new Example();
example.executeQuery();
} catch (Exception ex) {
System.out.println("An exception : " + ex.getMessage());
}
}
private void executeQuery() throws SQLException {
Statement st = null;
try {
System.out.println("Please enter an int");
new Scanner(System.in).nextInt();
st = this.ucaConn.createStatement();
System.out.println("Please enter an int");
new Scanner(System.in).nextInt();
ResultSet rs = st.executeQuery("Select * from PersonData where EngNo = '1544256'");
System.out.println(" result:");
dump (rs, "executeQuery");
} catch(Exception ex) {
System.out.println("Sarah exception: " + ex.getMessage());
} finally {
if ( st != null ) {
st.close();
}
}
}
private Connection getUcanaccessConnection(String pathNewDB) throws SQLException, IOException {
String url = UcanaccessDriver.URL_PREFIX + "VehicleDatabase2.mdb;newDatabaseVersion=V2003";
return DriverManager.getConnection(url);
}
private void dump(ResultSet rs, String exName)
throws SQLException {
System.out.println("-------------------------------------------------");
System.out.println();
System.out.println();
int jk = 0;
while (rs.next()) {
System.out.print("| ");
int j=rs.getMetaData().getColumnCount();
for (int i = 1; i <=j ; ++i) {
Object o = rs.getObject(i);
System.out.print(o + " | ");
}
System.out.println();
System.out.println();
}
}
}
When it runs on my laptop, the connection takes only about a minute to establish.
But when it runs on my Android device, the connection takes more than 10 minutes, and takes up all the heap space, and when the device runs out of memory, the app crashes
What should i do??
Note:
i made some slight changes in this code to run it on android, like adding toasts instead of System.out.println for debugging, i removed the static main function for android, used Environment.getAbsolutePath() to locate the database, etc.
Also, the code that I am running on Android, I first used a 9MB database to check if it works. The code fetches the data as expected from the 9MB database without any issues. The connection takes around 10 seconds to establish in Android in case of the 9MB database (in desktop, it takes less than a second to establish connection with 9MB database)
Yes, I know, it should work on a medium sized db. With a huge one...
Firstly, notice that the time you're measuring, it's the time of the very first connection to the database in the VM life, the followings(if needed) will be instantaneous.
Never tried something like that on Android because your experiment is challenging, yet, should it fit your requirements, you may try:
-use MirrorFolder (or keepMirror) connection parameter(see the ucanaccess web site for more details about it). In this case the very first connection to the db will be very slow, all the followings(even if the vm ends) will be instantaneous. But the access database should be updated only with ucanaccess and on your android
or, alternatively
-use a filter database(configure it on windows) that links the real database within the subset of external linked tables which are closely needed for your app(the memory usage might be dropped down). In this case, you'll have to use the remap connection parameter, because you're on a linux based SO.
See another suggestion related to jackcess(the underlying I/O library) here and use the latest ucanaccess release.
Below is my code
for(int j=0;j<6;j++){
//checking each deal
dealname=driver.findElement(By.id("MainContent_dtlstAllDeals_lblDealTitle_"+j)).getText();
// System.out.println(dealname);
String result[]=dealname.split("\\.");
String resultTitle=result[0];
//System.out.println(resultTitle);
String splitDealname=DealTitle.substring(0,resultTitle.length());
if(splitDealname.equals(resultTitle)){
System.out.println("***whoooooo you got it********"+j+"position"+"in"+i+"page");
//click on view deal button
driver.findElement(By.id("MainContent_dtlstAllDeals_lbtnView_"+j)).click();
Thread.sleep(5000);
//System.out.println(driver.findElement(By.id("MainContent_lblDealTitle")).getText());
String name=driver.findElement(By.id("MainContent_lblDealTitle")).getText();
//verify selected deal is correct
System.out.println(name);
//Thread.sleep(5000);
try {
if (name.equals(DealTitle)) {
System.out.println("whoos...verified");
}
/*
String statuss=veifyTitle("");
if(statuss.equals("success")){
{
System.out.println("whoos...verified");
//do buying process
}
}
else{}*/
} catch (Exception e) {
// TODO: handle exception
System.out.println(e);
}
}
Even though variables DealTitle and name contain same long string as below , that above code is not working.I have put the code in for loop , but when the 'if' condition is run it goes to next iteration .I found it while debugging
Detailed Interior Cleaning + Exterior Car Wash (External Foam Wash, Shampooing, Conditioning, Engine Room Wash, Tyre Polishing) Using AUTOGLYM Brand Products for Just Rs. 399 from Hasten Auto, Vennala (76% OFF)-pramod
Pls help.
I got issue solved by using replace all method
String excelTitle= DealTitle.replaceAll("[^\\w\\s\\-_]", "");
String pageTitle=name.replaceAll("[^\\w\\s\\-_]", "");
if(excelTitle.compareTo(pageTitle)==0){
System.out.println("ok strings are same");
}
Or you can use name.replaceAll("[^a-zA-Z]", "")
I'm using the following code to get the response from a servlet. It will check whether the given name in the variable "get" is in a particular table, and print 1 if it exists.
Portion of servlet code:
get = request.getParameter("nam");// such as get="kannan"
try {
// Connection code
ResultSet rs = stmt
.executeQuery("select * from newfarmer where rname='" + get
+ "'");
while (rs.next()) {
username = rs.getString("rname");
if (get.equals(username)) {
out.println(1);
}
}
} catch (Exception e) {
out.println(e.toString());
}
In my android application, I check this response as follows:
response = CustomHttpClient.executeHttpPost(
"http://moberp.svsugar.com:8080/androidservlt/Modify",
postParameters);
String res = response.toString();
res = res.trim();
if (res.equals("1")) {
flag = 1;
Toast.makeText(getBaseContext(), "Correct", Toast.LENGTH_LONG)
.show();
} else {
flag = 2;
Toast.makeText(getBaseContext(), "please enter correct Ryot name",
Toast.LENGTH_LONG).show();
}
It works very well for single record. I mean, in the table "newfarmer", If "rname" consists of more than one same name only the else part is executed.
Example:
If "kannan" is presented 2 times in the table Servlet output is as
1 1
Now in android application, clearly the else part is executed because response is not 1.
This is only case of two same names. The table may contains more than 10 same names.
If 10 same names, then servlet output is as
1 1 1 1 1 1 1 1 1 1
So I need to check all.
So I need to make changes in my if condition, but I don't know what to do. Someone please give answer.
Thanks in advance
instead of while loop Use
if(rs.next())
Now it will print only one time.
No change in android
in servlet do this
if(rs.next())
{
username=rs.getString("rname");
if(get.equals(username))
{
out.println(1);
}
}
}
this loop will run only 1 time now if the record is present.
I don't understand why would get.equals(username) will evaluate to false when you are having a where clause in your SQL query?
So just try this.
if(rs.next())
{
// The above condition will make the code inside if executed
// only if any matching record is found and
//hence it will print `1` only once
//if any matching record is found.
username=rs.getString("rname");
if(get.equals(username))
{
out.println(1);
}
}
Also you are using stmt.executeQuery("select * from newfarmer where rname='"+get+"'");
which is susceptible to SQL injection.
So better use prepared statement instead.
try if(rs.next()),
this will surely help you