Connect Processing with SQL database and Get name of columns - mysql

I have connect Processing and SQL by using database library "de.Bezier.data.sql".
I don't know How can I get the name of columns in a specific Table.
I get the correct name of database, but i got the following as result of name of columns "Tables_in_sql7363100"
import de.bezier.data.sql.*;
MySQL sql;
String[] tableNames;
String[] columnNames;
void setup() {
size(300, 300);
database_connection();
if (connect) {
tableNames = sql.getTableNames();
for (int i=0; i<tableNames.length; i++) {
println(tableNames[i]);
}
columnNames = sql.getColumnNames();
for (int i=0; i<ColumnNames.length; i++) {
println(columnNames[i]);
}
}
}
void draw() {
background(255);
}
void database_connection() {
sql = new MySQL(this, "ServerName", "DataBase", "DUN", "PW");
if (sql.connect()) {
connect = true;
connect_status = "Conected";
} else {
connect = false;
connect_status = "Connection Failed";
}
}

There are 2 problems with what I'm seeing. The first one, which interests you, is that you didn't select any table. That's why you don't get a list of columns. You can fix this by using a simple query:
sql.query("SELECT * FROM myTable");
But that's not the only thing: you're not accounting for lag. It may work for now on a local database because lag is really low, but this won't fly with something which is over the internet. Here's an example where I show columns from a public test database and how long it takes to get the result from my query back:
import de.bezier.data.sql.*;
MySQL sql;
String user = "rfamro";
String pass = "";
String server = "mysql-rfam-public.ebi.ac.uk:4497";
String database = "Rfam";
String[] columnNames;
void setup() {
size(300, 300);
sql = new MySQL(this, server, database, user, pass);
}
void draw() {
if (columnNames != null) {
println("It took " + millis() + "ms to get this data back.");
for (String s : columnNames) {
println(s);
}
noLoop();
} else if (sql.connect()) {
sql.query("SELECT * FROM family");
sql.next(); // only use .next when you know you have data
columnNames = sql.getColumnNames();
}
}
From here, it takes between 2-7 seconds to get the data back. You'll understand that, the setup() method running taking about a couple milliseconds, you won't have any results back by then.
Hope this helps. Have fun!

Related

MySQL query only inserting some data and sorting data

I have two issues here. Let me describe the goal of the program first. I simply want to populate a company_id row of my table with 100000 string ids ranging from 00000-99999, shuffled, with no repeats. I was successful in creating an array like this. Now, I am trying to fill my primary key column with this array. As seen in my code below, I am trying to do this with a for loop. I am new to MySQL, so I am unsure if this is an efficient way to insert an array into a column. The first issue is that only 1000 strings are entered. The second issue is that it sorts the strings by number (00000, 00001, etc). My code is below. Any ideas? Thanks.
Update:
I solved one of the issues. I was silly enough to think that it would show the table in it's entirety. I simply went to MySQLWorkbench > Preferences > SQL Execution > Limit Rows Count. Still don't understand why it is automatically sorting my table by primary key.
package populateDB;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Random;
public class PopulateDB {
public static void main(String[] args) {
int[] nums = new int[100000];
String[] ids = new String[100000];
// Fill array with numbers 0-99999
for(int i = 0; i < ids.length; i++) {
nums[i] = i;
}
// Fill array to give length
Arrays.fill(ids, "fill");
shuffleArray(nums);
// Changes numbers such as 235 to 00235
for(int i = 0; i < ids.length; i++) {
ids[i] = createString(nums[i]);
}
try
{
// Create a MySQL database connection
String myDriver = "org.gjt.mm.mysql.Driver";
String myUrl = "jdbc:mysql://localhost:3306/humansight_schema";
Class.forName(myDriver);
Connection conn = DriverManager.getConnection(myUrl, "root", "password");
// The MySQL insert statement
String query = " insert into user_data (company_id)"
+ " values (?)";
for(int i = 0; i < ids.length; i++) {
// Create the MySQL insert PreparedStatement
PreparedStatement preparedStmt = conn.prepareStatement(query);
preparedStmt.setString (1, ids[i]);
// Execute the PreparedStatement
preparedStmt.execute();
}
conn.close();
System.out.println("Done");
}
catch (Exception e)
{
System.err.println("Got an exception!");
System.err.println(e.getMessage());
}
}
private static void shuffleArray(int[] array)
{
int index;
Random random = new Random();
for (int i = array.length - 1; i > 0; i--)
{
index = random.nextInt(i + 1);
if (index != i)
{
array[index] ^= array[i];
array[i] ^= array[index];
array[index] ^= array[i];
}
}
}
private static String createString(int num) {
String numString = Integer.toString(num);
int zeroesToAdd = 5 - numString.length();
String zeroes = "";
for(int i = 0; i < zeroesToAdd; i++) {
zeroes = zeroes.concat("0");
}
return zeroes.concat(numString);
}
}

SqlDependency failed because A SELECT statement that cannot be notified or was provided

I'm trying to use SqlDependency, And I read articles Creating a Query for Notification, Query Notification Permissions from Microsoft. I double checked many times, it seems all meet what it needs which mentions in articles Here is my code.
private void InitialSqlDependency()
{
using (var connection = new SqlConnection(_connString))
{
connection.Open();
string message = string.Empty;
string query = #"SELECT ModifiedOn FROM [dbo].[ContainerTransactions]";
using (var command = new SqlCommand(query, connection))
{
command.Notification = null;
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(Dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
SqlDataReader dr = command.ExecuteReader();
if (dr.HasRows)
{
dr.Read();
message = dr[0].ToString();
}
}
}
}
private void Dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
_logger.Debug("ContainerWatch Dependency Fired!");
if (e.Type == SqlNotificationType.Change)
{
_logger.Debug("ContainerWatch Change Fired!");
this.InitialSqlDependency();
}
}
However, It always failed to subscribe. And I see SqlNotificationInfo returns Query which means A SELECT statement that cannot be notified or was provided. Here is my debug img
The SELECT statement is extremely simple, Is there any possible reason causing fail?
I found the root cause, because The statement must not reference tables with computed columns. I use a query below to see computed columns
SELECT * FROM sys.computed_columns WHERE object_id = OBJECT_ID('ContainerTransactions')
Therefore, I think I can't use SqlDependency on this table.

Rename value within query

I have a problem with renaming a specific value in a column in mySQL Database. At first i thought i could just use 'AS' to rename, but i'm actually trying to rename a value in a column. My column is named FoundLost. In this column I Store values '0' and '1'. '0' is Found and '1' is Lost.
The reason I need to rename this values is because I use the data from this database to create a pieChart. with the function .getName it gives the names '0' and '1'.
I was hoping someone could help me out!
The class with the query is the code below:
public static ObservableList getPChartFoundLost() {
String query = "SELECT FoundLost, concat(round(count(FoundLost) *100 / (SELECT count(FoundLost) FROM Luggage))) AS percent FROM Luggage GROUP BY FoundLost";
ObservableList FoundLost = FXCollections.observableArrayList();
Connection connection = DatabaseUtils.connect();
if (connection != null) {
try {
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query);
while (resultSet.next()) {
FoundLost.add(new PieChart.Data(resultSet.getString("FoundLost"), resultSet.getInt("percent")));
}
resultSet.close();
statement.close();
} catch (SQLException sqle) {
System.out.println(sqle.getMessage());
}
DatabaseUtils.disconnect(connection);
}
return FoundLost;
}
Controller:
public void clickPChartFoundLost(ActionEvent event) {
//PieChart
ObservableList FoundLost = StatisticsUtils.getPChartFoundLost();
pieChart.setVisible(true);
pieChart.setData(FoundLost);
pieChart.setTitle("Found and Lost luggage");
for (final PieChart.Data data : pieChart.getData()) {
data.getNode().addEventHandler(MouseEvent.ANY,
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
//Label vullen met data van Observable list uit Database
pieChartValueLable.setText(String.valueOf(data.getName()) + ": "
+ String.valueOf(data.getPieValue()) + "%");
}
});
}
}
Thanks!!
In your query, try this as your first column instead of just FoundLost. It translates your 0 and 1 values to meaningful strings for your chart. The rest of your query can stay the same.
IF(FoundLost = 0,'Found','Lost') AS FoundLost

How to get data from database javafx

I have this project and I need to get data (writing) from a database and I am using javaFX. I have a connection class that works (when I run it makes the connection)
public class Conexiune extends JPanel {
public Connection con = null;
public Statement stmt = null;
public ResultSet rs = null;
Vector data = null;
Vector columns = null;
JTable table;
JPanel paneOrar;
JTable tabel;
void login() throws SQLException {
String url = "jdbc:mysql://localhost:3308/database";
String login = "root";
String password = "password";
con = (Connection) DriverManager.getConnection(url, login, password);
}
Component query() throws SQLException {
stmt = con.createStatement();
ResultSet result = stmt.executeQuery("SELECT * FROM data");
ResultSetMetaData md = (ResultSetMetaData) result.getMetaData();
int columnCount = md.getColumnCount();
Vector columns = new Vector(columnCount);
// store column names
for (int i = 1; i <= columnCount; i++)
columns.add(md.getColumnName(i));
Vector data = new Vector();
Vector row;
// store row data
while (result.next()) {
row = new Vector(columnCount);
for (int i = 1; i <= columnCount; i++) {
row.add(result.getString(i));
}
data.add(row);
}
JScrollPane scrollPane = new JScrollPane(tabel);
this.setLayout(null);
JTable table = new JTable(data, columns);
return this.add(table);
}
Conexiune() {
try {
login();
System.out.println("bdConnect");
} catch (SQLException sqle) {
System.err.println(sqle);
}
}
}
After I run I get the message bdConnect with no errors.
The main problem is that i don't know what to do after, I mean I want to get the text from the database on to something that is not a table. Something like a scrollPane. Lets say i just want a window full of text on multiple lines but not a table. Lets say that you want to get the contents of a book from your database, you cant put it in a table. Can anyone help me please I'm getting kind of desperate!!!

Connection pool connections consumed when in TransactionScope

Can someone explain why we are experiencing a total consumption of the connection pool when performing queries inside TransactionScope resulting in
System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
I have reduced our problem to the following:
SomeNonTransactionalCode()
{
// This code will execute with just one connection to the database
// and complete without exception
List<BusinessEntity> beList;
for (int i = 0; i < 101; i++)
{
BusinessEntityRepository beRepo = new BusinessEntityRepository();
beList = beRepo.ReadAll().ToList();
}
}
SomeTransactionalCode()
{
// This code will cause the connections to the database to increment
// with every iteration eventually timing out after 100 connections
using (TransactionScope transactionScope = new TransactionScope())
{
List<BusinessEntity> beList;
for (int i = 0; i < 101; i++)
{
BusinessEntityRepository beRepo = new BusinessEntityRepository();
beList = beRepo.ReadAll().ToList();
}
transactionScope.Complete();
}
}
EDIT
After Omer's answer below I think the problem is explained better like this:
SomeNonTransactionalCode()
{
// This code will execute with just one connection to the database
List<BusinessEntity1> be1List;
BusinessEntity1Repository be1Repo = new BusinessEntity1Repository();
be1List = be1Repo .ReadAll().ToList();
List<BusinessEntity2> be2List;
BusinessEntity2Repository be2Repo = new BusinessEntity2Repository();
be2List = be2Repo .ReadAll().ToList();
List<BusinessEntity3> be3List;
BusinessEntity3Repository be3Repo = new BusinessEntity3Repository();
be3List = be3Repo.ReadAll().ToList();
}
SomeTransactionalCode()
{
// This code will cause three seperate connections to the database
using (TransactionScope transactionScope = new TransactionScope())
{
// note this is simplified - the code below could be in unknown nested
// methods make creating of the repos prior to calling not possible
List<BusinessEntity1> be1List;
BusinessEntity1Repository beRepo1 = new BusinessEntity1Repository();
be1List = be1Repo.ReadAll().ToList();
List<BusinessEntity2> be2List;
BusinessEntity2Repository beRepo2 = new BusinessEntity2Repository();
be2List = be2Repo.ReadAll().ToList();
List<BusinessEntity3> be3List;
BusinessEntity3Repository beRepo3 = new BusinessEntity3Repository();
be3List = be3Repo.ReadAll().ToList();
transactionScope.Complete();
}
}
Surely this is not expected behaviour? I have read nothing that explains why this might be happening. I can only assume it is something to do with how we have implemented our repositories. Hopefully the following will give a good enough description of the implementation.
public class BusinessEntityRepository
{
private BusinessEntityDal Dal { get; set; }
public BusinessEntityRepository()
{
this.Dal = new BusinessEntityDal ();
}
public IQueryable<BusinessEntity> ReadAll()
{
IQueryable<BusinessEntity> query = null;
if (Dal != null)
{
query = Dal.ReadAll();
}
//-Return
return query;
}
}
public class BusinessEntityDal : BaseDal
{
public IQueryable<BusinessEntity> ReadAll()
{
var result = from de in this.DC.BusinessEntityTable
select new BusinessEntity
{
Property1 = Column1,
Property2 = Column2,
// etc...
};
//-Return
return (result);
}
}
public abstract class BaseDal
{
protected OurDataContext DC;
public BaseDal()
{
// create a DataContext
this.DC = new OurDataContext();
}
}
public class OurDataContext : System.Data.Linq.DataContext
{
private static readonly string _cn = // some static connection string taken from web.config
public OurDataContext()
: base(OurDataContext._cn)
{
}
}
Our connection string is fairly conventional and leaves the number of connections in the pool at the default 100 (hence the 101 iterations to test the issue in my code above).
You are creating new DataContext references inside the for loop.
for (int i = 0; i < 101; i++)
{
BusinessEntityRepository beRepo = new BusinessEntityRepository();
beList = beRepo.ReadAll().ToList();
}
It is keeping all those in different transactions. If you just put repo init code outside the for loop and perform all operations in one context, it will be fine.
using (TransactionScope transactionScope = new TransactionScope())
{
List<BusinessEntity> beList;
BusinessEntityRepository beRepo = new BusinessEntityRepository();
for (int i = 0; i < 101; i++)
{
beList = beRepo.ReadAll().ToList();
}
//do some other things with same context
transactionScope.Complete();
}