I created a database using DB Browser for SQLite. Now I am trying to run queries to retrieve data from the database, and I have run into an issue. When I run the query in DB Browser, the query runs smoothly. When I attempt to run the same query in Java, I get an error message. I triple-checked the query string. I looked to make sure I was not using SQLite keywords incorrectly. Why am I getting an error when I run this query Java?
SELECT
subject.id, main.name, main.link, subject.name, main_subject.weight
FROM
main_subject
LEFT JOIN
main ON main_subject.mainId = main.id
LEFT JOIN
subject ON main_subject.subjectId = subject.id
The query running correctly in DB Browser.
MCVE:
Main
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* #author sedrick
*/
public class Main
{
public static void main(String[] args)
{
try (DatabaseHandler databaseHandler = new DatabaseHandler()) {
List<BySubjectItemTwo> bySubjectItemTwos = databaseHandler.getBySubjectItems();
bySubjectItemTwos.forEach(System.out::println);
//databaseHandler.getByTitleItems().forEach(System.out::println);
}
catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
DatabaseHandler
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author sedrick
*/
public class DatabaseHandler implements AutoCloseable
{
String dbString = "jdbc:sqlite:qDatabase.sqlite3";
private Connection conn;
public DatabaseHandler()
{
try {
conn = DriverManager.getConnection(dbString);
System.out.println("Connected to qDatabase!");
}
catch (SQLException ex) {
Logger.getLogger(DatabaseHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void close() throws Exception
{
conn.close();
}
public List<BySubjectItemTwo> getBySubjectItems()
{
List<BySubjectItemTwo> returnList = new ArrayList();
String sqlString = "SELECT subject.id, main.name, main.link, subject.name, main_subject.weight FROM main_subject LEFT JOIN main ON main_subject.mainId = main.id LEFT JOIN subject ON main_subject.subjectId = subject.id";
try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sqlString)) {
while (rs.next()) {
System.out.println(rs.getInt("subject.id") + " - " + rs.getString("main.name") + " - " + rs.getString("main.link") + " - " + rs.getString("subject.name") + " - " + rs.getInt("main_subject.weight"));
//returnList.add(new BySubjectItemTwo(rs.getInt("subject.id"), rs.getString("main.name"), rs.getString("main.link"), rs.getString("subject.name"), rs.getInt("main_subject.weight")));
}
}
catch (SQLException e) {
System.out.println(e.getMessage());
}
return returnList;
}
}
BySubjectItemTwo
/**
*
* #author sedrick
*/
public class BySubjectItemTwo
{
private int subjectId;
private String mainName;
private String mainLink;
private String subjectName;
private int mainSubjectWeight;
public BySubjectItemTwo(int subjectId, String mainName, String mainLink, String subjectName, int mainSubjectWeight)
{
this.subjectId = subjectId;
this.mainName = mainName;
this.mainLink = mainLink;
this.subjectName = subjectName;
this.mainSubjectWeight = mainSubjectWeight;
}
public int getSubjectWeight()
{
return mainSubjectWeight;
}
public void setSubjectWeight(int mainSubjectWeight)
{
this.mainSubjectWeight = mainSubjectWeight;
}
public int getSubjectId()
{
return subjectId;
}
public void setSubjectId(int subjectId)
{
this.subjectId = subjectId;
}
public String getMainName()
{
return mainName;
}
public void setMainName(String mainName)
{
this.mainName = mainName;
}
public String getMainLink()
{
return mainLink;
}
public void setMainLink(String mainLink)
{
this.mainLink = mainLink;
}
public String getSubjectName()
{
return subjectName;
}
public void setSubjectName(String subjectName)
{
this.subjectName = subjectName;
}
#Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("BySubjectItemTwo{subjectId=").append(subjectId);
sb.append(", mainName=").append(mainName);
sb.append(", mainLink=").append(mainLink);
sb.append(", subjectName=").append(subjectName);
sb.append(", subjectWeight=").append(mainSubjectWeight);
sb.append('}');
return sb.toString();
}
}
Error
----------< sed.work:CreateDatabaseByTitleAndSubjectDatabase >----------
Building CreateDatabaseByTitleAndSubjectDatabase 1.0-SNAPSHOT
--------------------------------[ jar ]---------------------------------
--- exec-maven-plugin:1.5.0:exec (default-cli) # CreateDatabaseByTitleAndSubjectDatabase ---
Connected to qDatabase!
[SQLITE_ERROR] SQL error or missing database (ambiguous column name: subject.id)
------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Total time: 1.484 s
Finished at: 2020-10-16T12:42:35-05:00
------------------------------------------------------------------------
Netbean's Info
Product Version: Apache NetBeans IDE 12.1
Java: 15; Java HotSpot(TM) 64-Bit Server VM 15+36-1562
Runtime: Java(TM) SE Runtime Environment 15+36-1562
System: Windows 10 version 10.0 running on amd64; Cp1252; en_US (nb)
Maven Project
This:
FROM main_subject, main, subject
is the problem with your query.
Remove , main, subject from your statement.
The tables main and subject are correctly joined after the LEFT joins.
When you use them also in the FROM clause this creates additional references and CROSS joins to the same tables.
Also, although SQLite allows a query to return more than 1 columns with the same name, it is a good practice to alias columns so that in the resultset all column names are different.
So give aliases to main.name and subject.name, something like this:
SELECT subject.id, main.name AS main_name, ..., subject.name AS subject_name, ...
and when you retrieve the column values don't use the table prefixes:
System.out.println(rs.getInt("id") + " - " + rs.getString("main_name") + " - " + rs.getString("link") + " - " + rs.getString("subject_name") + " - " + rs.getInt("weight"));
Related
I'm requesting your feedback on a test I was asked to setup in java: extract data from an Oracle table (no WHERE CLAUSE) and store it in a flat file.
Some may say Oracle provides tools to do so and probably better than me but I was asked to wrote my own tool.
I have 2 source table identical except that one is partitioned so my assumption was "if several threads can query each partition and wrote the content in its own file then I expect the extraction of a partitioned table to be faster than a regular table" but my test showed the opposite so I'm bit puzzled and I'd like to have your feedback.
Tables definition (250M rows each)
tab_non_partitioned (row_num number, row_label char(50));
tab_partitioned (row_num number,row_label char(50))
PARTITION BY RANGE(row_num)
PARTITION part_01 VALUES LESS THAN (50000001) TABLESPACE sst_01,
PARTITION part_02 VALUES LESS THAN (100000001) TABLESPACE sst_02,
PARTITION part_03 VALUES LESS THAN (150000001) TABLESPACE sst_03,
PARTITION part_04 VALUES LESS THAN (200000001) TABLESPACE sst_04,
PARTITION part_05 VALUES LESS THAN (250000001) TABLESPACE sst_05);
My tool has the following design:
class OracleWorker: this class executes the select statement and write the content in a file
class OracleExporter: this class checks if the table is partitioned then exec OracleWorker threads to do the extract
-if table is not partitioned then 1 OracleWorker thread is executed to extract the whole content
-if table is partitioned then each partition is queried by an individual thread. So in my example 5 threads will be executed and dump content in 5 different files
classDbExporter: the main class
Below are the classes details (sorry but I'm beginning with java coding so some piece of it might be ugly and I apologize in advance)
OracleWorker.java:
package DbExporter;
import org.apache.log4j.Logger;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Path;
import java.sql.*;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
public class OracleWorker implements Callable<Void> {
private static Logger logger = Logger.getLogger(OracleExporter.class.getName());
private Connection conn;
private String sqlStmt;
private int fetchSize;
private Writer outW;
OracleWorker(Connection conn, String sql, int size, Path out) throws IOException {
this.conn = conn;
this.sqlStmt = sql;
this.fetchSize = size;
this.outW = new BufferedWriter(new FileWriter(out.toString()), 32768);
logger.debug("sql to exec: " + sql);
logger.debug("output: " + out);
}
public Void call() throws Exception {
Statement stmt = null;
ResultSet rset = null;
ResultSetMetaData metaData;
Instant start, startResult;
int numOfCols;
List<Long> dbgRowToString = new ArrayList<>();
List<Long> dbgWrite = new ArrayList<>();
StringBuilder currentRow;
try{
stmt = this.conn.createStatement();
stmt.setFetchSize(this.fetchSize);
start = Instant.now();
rset = stmt.executeQuery(this.sqlStmt);
logger.debug(String.format("sql exec: %s ms", Duration.between(start, Instant.now()).toMillis()));
metaData = rset.getMetaData();
numOfCols = metaData.getColumnCount();
startResult = Instant.now();
while (rset.next()) {
currentRow = new StringBuilder();
start = Instant.now();
for (int i =1; i<numOfCols; i++) currentRow.append(rset.getString(i)).append("|");
currentRow.append(rset.getString(numOfCols));
dbgRowToString.add(Duration.between(start, Instant.now()).toMillis());
start = Instant.now();
this.outW.write(currentRow + System.lineSeparator());
dbgWrite.add(Duration.between(start, Instant.now()).toMillis());
}
logger.debug(String.format("fetch result: %s ms", Duration.between(startResult, Instant.now()).toMillis()));
logger.debug(String.format("avg row to string: %,.4f", dbgRowToString.stream().mapToLong(a -> a).summaryStatistics().getAverage()));
logger.debug(String.format("avg write to file: %,.4f", dbgWrite.stream().mapToLong(a -> a).summaryStatistics().getAverage()));
}
catch (SQLException e){
logger.error("error executing statement");
throw e;
}
finally {
if(rset != null) rset.close();
if(stmt != null) stmt.close();
this.outW.close();
}
return null;
}
}
OracleExporter.java:
package DbExporter;
import oracle.jdbc.pool.OracleDataSource;
import org.apache.log4j.Logger;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class OracleExporter {
private static Logger logger = Logger.getLogger(OracleExporter.class.getName());
private Properties props;
private Connection conn;
OracleExporter(Properties prop) throws SQLException {
this.props = prop;
try{
OracleDataSource ods = new OracleDataSource();
String url = String.format("jdbc:oracle:thin:#//%s:%s/%s", prop.getProperty("db.hostname"), prop.getProperty("db.port"), prop.getProperty("db.name"));
ods.setURL(url);
ods.setUser(prop.getProperty("db.user"));
ods.setPassword(prop.getProperty("db.password"));
this.conn = ods.getConnection();
} catch (SQLException e) {
logger.error("error instantiating a connection");
throw e;
}
}
void execStmt() throws Exception {
Instant start;
List<String> sqlPartition = new ArrayList<>();
List<Path> outPartition = new ArrayList<>();
String unitPartition;
String tabName = this.props.getProperty("sql.table").toUpperCase();
Path outF = Paths.get(this.props.getProperty("output.dir"), tabName + ".csv");
// add oracle hint /*+ PARALLEL */ in the sql statement
String sqlNoPartition = String.format(
"SELECT /*+ PARALLEL */ %s FROM %s",
this.props.getProperty("sql.cols").toUpperCase(), tabName);
// check if table is partitioned
Statement stmt = this.conn.createStatement();
String sqlCheckPartition = String.format(
"SELECT PARTITION_NAME FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = '%s'", tabName);
ResultSet rset = stmt.executeQuery(sqlCheckPartition);
while (rset.next()){
unitPartition = rset.getString("PARTITION_NAME");
sqlPartition.add(sqlNoPartition + String.format(" PARTITION(%s)", unitPartition));
outPartition.add(Paths.get(this.props.getProperty("output.dir"), tabName + "_" + unitPartition + ".csv"));
}
rset.close();
stmt.close();
ExecutorService executorService = Executors.newFixedThreadPool(10);
List<OracleWorker> callableTasks = new ArrayList<OracleWorker>();
if (sqlPartition.isEmpty()) {
callableTasks.add(
new OracleWorker(
this.conn,
sqlNoPartition,
Integer.parseInt(this.props.getProperty("sql.fetch")),
outF)
);
}
else{
for (int i =0; i < sqlPartition.size();i++){
callableTasks.add(
new OracleWorker(
this.conn,
sqlPartition.get(i),
Integer.parseInt(this.props.getProperty("sql.fetch")),
outPartition.get(i)
)
);
}
}
start = Instant.now();
logger.info("TEST STARTING...please wait");
for (Future<Void> f : executorService.invokeAll(callableTasks)) f.get();
logger.info(String.format("TEST ELAPSED: %s ms", Duration.between(start, Instant.now()).toMillis()));
executorService.shutdown();
try {
if (!executorService.awaitTermination(800, TimeUnit.MILLISECONDS)) executorService.shutdownNow();
} catch (InterruptedException e) {
executorService.shutdownNow();
}
}
protected void finalize(){
try{
if(this.conn != null) this.conn.close();
}
catch (SQLException e){
e.printStackTrace();
}
}
}
DbExporter.java:
package DbExporter;
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
import org.apache.log4j.Logger;
public class DbExporter {
private static Logger logger = Logger.getLogger(DbExporter.class.getName());
private static void errorAndExit(String msg){
logger.error(msg);
System.exit(1);
}
public static void main(String[] args){
Properties properties = new Properties();
String configFile = System.getProperty("configFile", "");
OracleExporter cli;
try{
FileInputStream fis = new FileInputStream(new File(configFile));
properties.load(fis);
fis.close();
}
catch (Exception e){
errorAndExit("problem with file " + configFile);
System.exit(1);
}
try{
cli = new OracleExporter(properties);
cli.execStmt();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}
Finally my config file:
db.vendor=ORACLE
db.hostname=my_server
db.port=1521
db.name=MY_ORACLE_INSTANCE
db.schema=MY_ORACLE_SCHEMA
db.user=SST
db.password=xxx
sql.fetch=300
sql.table=tab_partitioned
sql.cols=row_num, row_label
output.dir=/storage_location/
Below are the result of my test
# execution on partitioned table
2022-04-28 15:05:04,442[main][OracleExporter][execStmt]-INFO- TEST STARTING...please wait
2022-04-28 15:16:08,430[main][OracleExporter][execStmt]-INFO- TEST ELAPSED: 663987 ms
# execution on non_partitioned table
bash$ /usr/local/java/jdk1.8.0_131-x64/bin/java -Dlogfilename=dbg.log -DconfigFile=sample_config.properties -jar db_exporter-1.0-SNAPSHOT-jar-with-dependencies.jar
2022-04-28 15:23:13,530[main][OracleExporter][execStmt]-INFO- TEST STARTING...please wait
2022-04-28 15:32:47,439[main][OracleExporter][execStmt]-INFO- TEST ELAPSED: 573909 ms
Please note that playing with the resultSet fetch size improved the timing but the non_partitioned table extraction is still faster than the partitioned table
I'd be happy to have your thoughts about my test and I thank you in advance
I changed my code by setting a dedicated connection per thread instead of a shared connection
I don't know if I need more coffee, or my head is tired, but, I feel like an idiot :)
what am I doing wrong???
I want to call the methods within the class but I get complile errors.
Compilation failure: Compilation failure:
java:[35,1] error: illegal start of type
java:[35,21] error: <identifier> expected
java:[35,22] error: ';' expected
I can't execute this block in the class
//this is what doesn't work
if (custkey.contains(",")) {
String[] ck = custkey.split(",");
for ( String k : ck) {
this.loadRefDb(k);
} else {
this.loadRefDb(custkey);
}
}
my class
package com.ge.digital.fleet.dataservice.impl.processor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.*;
import javax.naming.*;
import javax.sql.*;
import java.sql.*;
import com.ge.digital.fleet.dataservice.impl.db.RefDatabase;
public class RefReplicatedDataProcessor {
private static final Logger log = LoggerFactory.getLogger(RefReplicatedDataProcessor.class);
private RefDatabase refDb = null;
private DataSource dataSource;
private String custkey;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setCustkey(String custkey) {
this.custkey = custkey;
}
public void setRefDatabase(RefDatabase refDb) {
this.refDb = refDb;
}
//this is what doesn't work
if (custkey.contains(",")) {
String[] ck = custkey.split(",");
for ( String k : ck) {
this.loadRefDb(k);
} else {
this.loadRefDb(custkey);
}
}
public void loadRefDb(String custkey) throws SQLException {
log.info("Reference Replicated Data Processor :: start");
refDb.dropDb();
setAssociations(custkey);
refDb.replicationComplete();
log.info("Reference Replicated Data Processor :: Finish");
}
/***
* name: setAssociations(custkey)
* Loads/Builds the cache database with values found in mysql database
*
* returns a List of associations
* G1.DWATT,112-A-001_Gas_Turbine
* G1.ATID,112-A-001_Gas_Turbine
* G1.dvar, 112-A-001_Gas_Turbine
* ...
*/
public void setAssociations(String custkey) throws SQLException {
String reference = "";
String asset = "";
String dbname = "iprcmt1.fleet_associations"; //from old impl database - TODO new database impl
String query = "select reference, asset from " + dbname + " where custkey = ?";
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(query)) {
stmt.setString(1, custkey);
try (ResultSet rs = stmt.executeQuery()) {
if (! rs.next() ) {
log.info("SQL Warning ! No associations for key: " + custkey);
} else {
do {
reference = rs.getString(1);
asset = rs.getString(2);
log.info("SQL Associations reference: " + reference + " and asset: " + asset);
refDb.addRow(reference, asset);
} while (rs.next());
}
} catch (Exception ex) {
log.error("SQL Cannot Execute ResultSet Query!");
log.error(ex.getMessage());
}
} catch (Exception e) {
log.error("SQL Cannot Create DataSource Connection! Cannot Create Prepared Statement!");
log.error(e.getMessage());
}
}
}
maybe this ? :)
if (custkey.contains(",")) {
String[] ck = custkey.split(",");
for ( String k : ck) {
this.loadRefDb(k);
}
}else {
this.loadRefDb(custkey);
}
Your code is simply out of place. The code at "//this is what doesn't work" needs to be inside a method or constructor.
public RefReplicatedDataProcessor(){
//this is what didn't work
if (custkey.contains(",")) {
String[] ck = custkey.split(",");
for ( String k : ck) {
this.loadRefDb(k);
}
} else {
this.loadRefDb(custkey);
}
}
Perhaps you should run the split within a method
public void filter(){
if (custkey.contains(",")) {
String[] ck = custkey.split(",");
for ( String k : ck) {
this.loadRefDb(k);
} else {
this.loadRefDb(custkey);
}
}
}
I am working on a Get object as retrieved from a table in Habse. I want to dynamically retrieve all column values related to that get since I don't know the exact name of column families
val result1 = hTable.get(g)
if (!result1.isEmpty) {
//binaryEpisodes = result1.getValue(Bytes.toBytes("episodes"),Bytes.toBytes("episodes"))
//instead of above retrieve all values dynamically
}
Simple way :
get rawcells and knowing CF , columns information.
You have to do something like below example
public static void printResult(Result result, Logger logger) {
logger.info("Row: ");
for (Cell cell : result.rawCells()) {
byte[] family = CellUtil.cloneFamily(cell);
byte[] column = CellUtil.cloneQualifier(cell);
byte[] value = CellUtil.cloneValue(cell);
logger.info("\t" + Bytes.toString(family) + ":" + Bytes.toString(column) + " = " + Bytes.toString(value));
}
}
Hbase Admin way : Hbase client API was exposed by HbaseAdmin class like below...
Client would be like
package mytest;
import com.usertest.*;
import java.io.IOException;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class ListHbaseTablesAndColumns {
public static void main(String[] args) {
try {
HbaseMetaData hbaseMetaData =new HbaseMetaData();
for(String hbaseTable:hbaseMetaData .getTableNames(".*yourtables.*")){
for (String column : hbaseMetaData .getColumns(hbaseTable, 10000)) {
System.out.println(hbaseTable + "," + column);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Use below class to Get HbaseMetaData..
package com.usertest;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.PageFilter;
import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;
public class HbaseMetaData {
private HBaseAdmin hBaseAdmin;
private Configuration hBaseConfiguration;
public HbaseMetaData () throws IOException {
this.hBaseConfiguration = HBaseConfiguration.create();
this.hBaseAdmin = new HBaseAdmin(hBaseConfiguration);
}
/** get all Table names **/
public List<String> getTableNames(String regex) throws IOException {
Pattern pattern=Pattern.compile(regex);
List<String> tableList = new ArrayList<String>();
TableName[] tableNames=hBaseAdmin.listTableNames();
for (TableName tableName:tableNames){
if(pattern.matcher(tableName.toString()).find()){
tableList.add(tableName.toString());
}
}
return tableList;
}
/** Get all columns **/
public Set<String> getColumns(String hbaseTable) throws IOException {
return getColumns(hbaseTable, 10000);
}
/** get all columns from the table **/
public Set<String> getColumns(String hbaseTable, int limitScan) throws IOException {
Set<String> columnList = new TreeSet<String>();
HTable hTable=new HTable(hBaseConfiguration, hbaseTable);
Scan scan=new Scan();
scan.setFilter(new PageFilter(limitScan));
ResultScanner results = hTable.getScanner(scan);
for(Result result:results){
for(KeyValue keyValue:result.list()){
columnList.add(
new String(keyValue.getFamily()) + ":" +
new String(keyValue.getQualifier())
);
}
}
return columnList;
}
}
I have a problem with my code i'm working on an antologie file using Protege OWL API (3.4.8) and i want to have all the classes define by the user in the ontologie , the problem is i keep having errors in the for loop i can't fix those errors, is there any way to get the classes.
package Test;
import java.util.Collection;
import javax.swing.text.html.HTMLDocument.Iterator;
import antlr.collections.List;
import edu.stanford.smi.protege.model.Cls;
import edu.stanford.smi.protegex.owl.ProtegeOWL;
import edu.stanford.smi.protegex.owl.jena.JenaOWLModel;
import edu.stanford.smi.protegex.owl.model.OWLDatatypeProperty;
import edu.stanford.smi.protegex.owl.model.OWLIndividual;
import edu.stanford.smi.protegex.owl.model.OWLModel;
import edu.stanford.smi.protegex.owl.model.OWLNamedClass;
import edu.stanford.smi.protegex.owl.model.OWLObjectProperty;
import edu.stanford.smi.protegex.owl.model.RDFSClass;
public class Class4 {
public static JenaOWLModel owlModel =null;
public static String scorKos_Uri="C:/Users/souad/Desktop/SCOR-KOS.owl";
//where my ontologie file exist
//change the URI by this
"http://protege.cim3.net/file/pub/ontologies/travel/travel.owl"; to have a
OWL file
/**
* #param args
*/
public static void main(String[] args) {
/**
* ontologie
*/
try {
owlModel=ProtegeOWL.createJenaOWLModelFromURI(scorKos_Uri);
System.out.println("Worked");
Collection classes = owlModel.getUserDefinedOWLNamedClasses();
for (Iterator it = classes.iterator(); it.hasNext();) {
OWLNamedClass cls = (OWLNamedClass) it.next();
Collection instances = cls.getInstances(false);
System.out.println("Class " + cls.getBrowserText() + " (" +
instances.size() + ")");
for (Iterator jt = instances.iterator(); jt.hasNext();) {
OWLIndividual individual = (OWLIndividual) jt.next();
System.out.println(" - " + individual.getBrowserText());
}
}
}catch (Exception exception) {
System.out.println("Error can't upload the ontologie ");
System.exit(1);
}
}
}
You're not importing java.util.Iterator.
I've recently starting working on a java webapp (JSP / Servlet) that was developed by the internal developer of a company.
This app randomly doesn't return data, and inspecting the log I found some NullPointerExceptions related to the classes' member variable which holds the database connection. Following the stack trace it seems that a second thread closes the connection after it ended its task leaving the first thread without a connection.
By the needs of the company the app uses different databases, one which rules appdata, and others which contain data the app has to retrieve. So every class attached to the main servlet may connect to one or more databases depending on the task it has to accomplish.
I'm not familiar with JavaEE but giving a look at the database connection class, I see nothing which protect threads from conflicting each other.
Which is the correct way to handle such connections?
This is the code of the Database handler:
package it.metmi.mmasgis.utils;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class DBManager
{
private String szDatabase;
private String szUsername;
private String szPassword;
private String szError;
private Connection db;
private boolean bConnected;
private Logger logger;
public DBManager(String szDBName)
{
this(szDBName, "", "");
}
public DBManager(String szDBName, String szName, String szPass)
{
szDatabase = szDBName;
szUsername = szName;
szPassword = szPass;
bConnected = false;
szError = "";
logger = LogManager.getFormatterLogger(DBManager.class.getName());
}
public boolean connect()
{
logger.entry();
try {
Class.forName("com.mysql.jdbc.Driver");
if(!szDatabase.isEmpty())
{
String szCon = "jdbc:mysql://localhost/" + szDatabase;
if(!szUsername.isEmpty())
{
szCon += "?user=" + szUsername;
if(!szPassword.isEmpty())
szCon += "&password=" + szPassword;
}
db = DriverManager.getConnection(szCon);
bConnected = true;
} else {
logger.error("No database name!!");
System.exit(0);
}
} catch(SQLException | ClassNotFoundException e) {
szError = e.getMessage();
e.printStackTrace();
logger.error("Can't connect: %s", e);
}
return logger.exit(bConnected);
}
public void disconnect()
{
logger.entry();
try {
db.close();
bConnected = false;
} catch(SQLException e) {
e.printStackTrace();
logger.error("Can't disconnect: %s", e);
}
logger.exit();
}
public boolean isConnected()
{
return bConnected;
}
public String getError()
{
return szError;
}
public ArrayList<HashMap<String,String>> query(String szQuery)
{
logger.entry(szQuery);
ArrayList<HashMap<String,String>> aResults = new ArrayList<HashMap<String,String>>();
int iCols = 0;
try {
Statement stmt = db.createStatement();
logger.info("Query: %s", szQuery);
ResultSet rs = stmt.executeQuery(szQuery);
ResultSetMetaData rsmd = rs.getMetaData();
iCols = rsmd.getColumnCount();
while(rs.next())
{
HashMap<String,String> pv = new HashMap<String,String>();
for(int i = 0; i < iCols; i++)
{
String szCol = rsmd.getColumnLabel(i + 1);
String szVal = rs.getString(i + 1);
pv.put(szCol, szVal);
}
aResults.add(pv);
}
rs.close();
stmt.close();
} catch(SQLException e) {
e.printStackTrace();
szError = e.getMessage();
logger.error("Error executing query: %s", e);
}
return logger.exit(aResults);
}
public boolean update(String szQuery)
{
logger.entry(szQuery);
boolean bResult = false;
try {
Statement stmt = db.createStatement();
logger.info("Query: %s", szQuery);
stmt.executeUpdate(szQuery);
bResult = true;
stmt.close();
} catch(SQLException e) {
e.printStackTrace();
szError = e.getMessage();
bResult = false;
logger.error("Error executing query: %s", e);
}
return logger.exit(bResult);
}
}
The class Task which all the servlet classes are based on, is a simple abstract class:
package it.metmi.mmasgis.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public abstract class Task
{
public abstract void doTask(HttpServletRequest request, HttpServletResponse response);
}
The class which throws NullPointerExceptions it this one, during the invocation of db.disconnect(). This class is called rapidly via AJAX 4 or 5 times from the interface written in JS.
package it.metmi.mmasgis.servlet.params;
import it.metmi.mmasgis.servlet.Task;
import it.metmi.mmasgis.utils.Const;
import it.metmi.mmasgis.utils.DBManager;
import it.metmi.mmasgis.utils.Query;
import it.metmi.mmasgis.utils.Utility;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ClassType extends Task
{
private DBManager db = null;
private Logger logger = LogManager.getFormatterLogger(ClassType.class.getName());
#Override
public void doTask(HttpServletRequest request, HttpServletResponse response)
{
logger.entry(request, response);
String szCensimento = Utility.getParameter(request, "censimento");
String szCategoria = Utility.getParameter(request, "category");
ArrayList<HashMap<String,String>> aClasses = new ArrayList<HashMap<String,String>>();
PrintWriter out = null;
logger.debug("Census: %s", szCensimento);
logger.debug("Category: %s", szCategoria);
db = new DBManager(szCensimento, Const.DB_USER, Const.DB_PASS);
if(db.connect())
{
String szQuery = String.format(Query.classes, szCategoria, szCategoria);
aClasses = db.query(szQuery);
db.disconnect();
}
try {
out = response.getWriter();
jsonEncode(aClasses, out);
} catch(IOException e) {
e.printStackTrace();
logger.error("Failed to encode JSON: %s", e);
}
logger.exit();
}
private void jsonEncode(ArrayList<HashMap<String,String>> aData, PrintWriter out)
{
HashMap<String,Object> result = new HashMap<String,Object>();
result.put("results", aData);
result.put("success", true);
Gson gson = new GsonBuilder().create();
gson.toJson(result, out);
}
}
If the webapp would use only one database, it could be rewritten as a Singleton, but in this way I have no idea on how to handle different connections for different databases.
How can avoid these exceptions?
The problem was that the connection object was declared as member.
Moving the variable inside the methods resolved.