I have a request that should extract data from three tables A, B, C based on two conditions, these tables A,B and C are located in the same data source.
does BIRT 3.1 supports joint data sets with more than two tables?
Otherwise, is there a way to overcome this limitation?
You don't say what your data source is, but assuming that it is a SQL data base. You can do something like this in the SQl. You only need to do BIRT joins if the data is in different data sources.
select TableA.Field
, TableB.OtherField
, TableC.SomeOtherField
from dbo.TableA
left join dbo.TableB
on TableA.Same = TableB.Same
left join dbo.TableC
on TableA.Same = TableC.Same
where TableA.Important = 'Something'
In addition to James' answer:
In many cases just joining the tables using SQL is the best solution (you should know SQL if you are developing with BIRT, unless someone else prepared the Data Sets and corresponding report items for you).
As an alternative, keep in mind that BIRT does not have a "data model" like other report designers (e.g. Oracle Reports) and that you link data from different data sets by creating a corresponding layout structure, with data set parameter bindings.
You didn't mention the logical structure of your data.
If it's master-detail-detail (for example, artist-album-title), then you would use for example a list item bound to DS "artist", containing a list or table item bound to DS "album" which in turn contains a table bound to DS "title".
The DS "album" would need a DS parameter like "artist_id" or whatever (which you use in the WHERE clause of the SELECT statement), and in the list/table item bound to DS "album", you would use row["artist_id"] as the value for the DS parameter "artist_id".
This is similar for the table item bound to DS "title". However, if the primary key consists of (artist_id, album_id, title_no), you probably need access to the current artist from the outer-most list item. To access this, you use row._outer["artist_id"].
The solution for this problem is using the stored procedure query, you set your proceure with whatever sql request you want, compile it with your DBMS, and you call it from BIRT with the syntax
call nameOfYourProceure{(?,?,?...)}
Question marks refer to the parameters that you will pass to your stored procedure.
Related
I've a database structure built with JPA. To give a little bit context - the user is shown a datatable and some (many...) filters with which he can filter the shown entries of the datatable. For example, every entry of the datatable corresponds to a certain factory (of e.g. 40 factories in total) and the user can filter for one or more factories.
To prevent overhead, the user can only filter by factories which occur in the dataset the datatable is built of, i.e. factories which would give an empty result after filtering (since there aren't any entries with this factory) aren't shown at all in the factory filter.
Furthermore, the datatable is paginated, i.e. just the first (second, third, etc.) 50 entries are given to the frontend but -- and that's the crucial point -- the filters should of course correspond to all entries (i.p. also the entries on the pages which are not shown). That means if factory B only occurs on page 2 and page 1 is loaded (i.e. there is no factory B under the shown entries resp. the entries the frontend receives), the factory filter should still list factory B.
My approach is the following: When constructing the result, using the same sql query, I get all values which one can filter by. So my constructed table looks so to say like this
factory | status | ...
F1 | done | ...
F2 | in progress | ...
F1 | in progress | ...
containing the entries over all pages (of which just the first (second, third, ...) 50 entries are given to the frontend) projected to the properties which one can filter by.
Now I just get the needes values by e.g. SELECT DISTINCT(entry.factory) FROM ... in a typed query. Basically, at this point I would create a sql view of the constructed table and get then 1) all distinct factories, 2) all distinct statuses, etc. pp. But JPA doesn't allow a CREATE VIEW when creating a typed query so at the moment, for each column I construct the same table (the one above) and get the distinct values in the current column.
(just for the sake of completeness: for performance reasons, it is not possible to get all entities and then iterate e.g. using the stream API over the list of results mapping to the "filterable" attributes, i.e. filtering has to happen directly in the database using SQL (i guess?))
I have two questions:
Is this implementation reasonable?
If yes, how can I approach the idea of creating a view? Ideally, directly via JPA but unfortunately I didn't find a real way to approach this using JPA.
Edit: To break it down to the very basic problem:
QueryPart queryPart = new QueryPartDTO("<some JPA query>");
QueryFactory<MyEntity> queryFactory = new QueryFactory<>();
final TypedQuery<MyEntity> query = queryFactory.buildTypedQuery(queryPart, entityManager, MyEntity.class);
List<MyEntity> resultList = query.getResultList();
// at this point, the query fires ↑
// that's okay because I do need the List<Entity> in order to give it to the frontend
// but instead of just getting a List<MyEntity>,
// I would like to have a sql view containing the result (resp. the whole result) as well
// because moreover, I have to get e.g. all factories, all statuses, etc.
// which occur in the given data - what could of course be done with
// the already given List<MyEntity> using the Stream API but since the list
// is in general very large, this approach would be to inefficient.
// Instead, I would like to do these computations using SQL - but for this,
// I need the data given by the constructed query above in a SQL table.
// Executing the query over and over again (and first, getting all distinct factories,
// second getting all distinct statuses, etc.) is not possible for
// performance reasons - the query is expensive. Hence, I need to
// save the result the query gives - in a way, I can execute some more
// queries on it: a view i guess.
Thanks in advance.
JPA doesn't support view creation indeed. It doesn't support any DDL queries.
Dynamic view creation is a fishy idea. Normally you design your database scheme only once. Moreover, you'll need separate views for different users which starts to sound like a nightmare.
What you can do is create a table with user filtering results, keyed with the user ID. Whenever the user applies his filters, you can DELETE the old result rows for this user and INSERT the new ones. Then you do the SELECT DISTINCT queries over this smaller dataset.
JPA won't help you with this too much since it doesn't support the INSERT SELECT SQL statement which you'll like to use here.
EDIT. I changed this answer to keep useful comments below. The previous version was completely different and not useful anyway.
I have a place where I store tables.
In this place I have a table. Lets' name it Table A. All columns in table A columns are varchars.
I want to create a process that will go through every table and create a new table in a different place in the database.
However this table has to have the right datatypes instead of varchars.
So if my column in table A is a column with the values 1234, I want to create a field that will be an INT an not a varchar.
I don't have any idea how to do it in java. Could somebody point me in the right direction on what things I would have to learn and if it is too difficult
Thanks
As I see it, your problem has a few parts:
EASY - Getting the existing table information. You'll have to get the DatabaseMetaData from your jdbc connection. Documentation on that class is here, and Google is your friend as to how to get that Object in the first place. (Hint: this question should get you most of the way )
MEDIUM - Figuring out what data type your data really is. If you try to narrow it down to just a few simple types like Integer, String, and dates, this might not actually be that hard. You'll just need to select a few rows for each column (where that column isn't null), and then try and parse it into different types. If it succeeds, it probably is that type. If it throws an Exception, then it's not. Integer.parseInt(), LocalDateTimeFormatter, etc. are the things you'll be using.
If you want to get table meta data, then just do a "SELECT * FROM < TABLE >" and the ResultSetMetaData will have all the information you'll need to keep going.
VERY HARD - Creating tables using the new, appropriate data types. This is hard not because of the stuff that's been mentioned so far, but because we haven't yet talked about foreign keys, indexes, and all that other good stuff. Mapping all those things programmatically will be a very hard problem. Therefore, I recommend NOT trying to program this part. Instead, have your script output the mapping of old datatypes to new datatypes for each table. Then you can go into your SQL mananger and get the SQL script to generate that table. Almost every SQL database management tool can generate the creation script for a table. Edit that script with your new datatypes, give it a new name, and run it.
I'm relatively new to working with JDBC and SQL. I have two tables, CustomerDetails and Cakes. I want to create a third table, called Transactions, which uses the 'Names' column from CustomerDetails, 'Description' column from Cakes, as well as two new columns of 'Cost' and 'Price'. I'm aware this is achievable through the use of relational databases, but I'm not exactly sure about how to go about it. One website I saw said this can be done using ResultSet, and another said using the metadata of the column. However, I have no idea how to go about either.
What you're probably looking to do is to create a 'SQL View' (to simplify - a virtual table), see this documentation
CREATE VIEW view_transactions AS
SELECT Name from customerdetails, Description from cakes... etc.
FROM customerdetails;
Or something along those lines
That way you can then query the View view_transactions for example as if it was a proper table.
Also why have you tagged this as mysql when you are using sqlite.
You should create the new table manually, i.e. outside of your program. Use the commandline 'client' sqlite3 for example.
If you need to, you can use the command .schema CustomerDetails in that tool to show the DDL ("metadata" if you want) of the table.
Then you can write your new CREATE TABLE Transactions (...) defining your new columns, plus those from the old tables as they're shown by the .schema command before.
Note that the .schema is only used here to show you the exact column definitions of the existing tables, so you can create matching columns in your new table. If you already know the present column definitions, because you created those tables yourself, you can of course skip that step.
Also note that SELECT Name from CUSTOMERDETAILS will always return the data from that table, but never the structure, i.e. the column definition. That data is useless when trying to derive a column definition from it.
If you really want/have to access the DB's metadata programatically, the documented way is to do so by querying the sqlite_master system table. See also SQLite Schema Information Metadata for example.
You should read up on the concept of data modelling and how relational databases can help you with it, then your transaction table might look just like this:
CREATE TABLE transactions (
id int not null primary key
, customer_id int not null references customerdetails( id )
, cake_id int not null references cakes( id )
, price numeric( 8, 2 ) not null
, quantity int not null
);
This way, you can ensure, that for each transaction (which is in this case would be just a single position of an invoice), the cake and customer exist.
And I agree with #hanno-binder, that it's not the best idea to create all this in plain JDBC.
Hello World, Here is the situation,
Basically instead of generating values from a table like like so
34.324, 09/13/2011, thankyou,
I would like to generate the type of that specific value
e.g
VarChar2, Date, varchar2(char 30)
Just to add another layer of difficulty a Java application pulls data from the multiple Oracle database tables using HQL. Thus I would need an equivalent HQL statement to the SQL statement (if it exists)..
I understand the DESC keyword lists the column data types for an entire table however as mentioned above I require specificity.
In Summary
I would like to reverse engineer this application to generate a report of the data_types of the data instead of the actual data itself. I could easily just manually walk through the code however they are over 200 entries and this will be a real pain.
Any help is truly appreciated. If this question is unclear please let me know and I will provide more details and examples.
I have followed Balusc's 1st method to create dynamic form from fields defined in database.
I can get field names and values of posted fields.
But I am confused about how to save values into database.
Should I precreate a table to hold values after creating form and
save values there manually (by forming SQL query manually)?
Should I convert name/value pairs to JSON objects
and save?
Should I create a simple table with id,name,value field and
save name/value pairs here (Like EAV Scheme)?
Or is there any way for persisting posted values into database?
Regards
It look like that you're trying to work bottom-up instead of top-down.
The dynamic form in the linked answer is intented to be reused among all existing tables without the need to manually create separate JSF CRUD forms on "hardcoded" Facelets files for every single table. You should already have a generic model available which contains information about all available columns in the particular DB table (which is Field in the linked answer). This information can be extracted dynamically and generically via JPA metadata information (how to do that in turn depends on the JPA provider used) or just via good 'ol JDBC ResultSetMetaData class once during application's startup.
If you really need to work bottom-up, then it gets trickier. Creating tables/columns during runtime is namely a very bad design (unless you intend to develop some kind of DB management tool like PhpMyAdmin or so, of course). Without the need to create tables/columns runtime, you should basically have 3 tables:
1 table which contains information about which "virtual" DB tables are all available.
1 table which contains information which columns one such "virtual" DB table has.
1 table which contains information which values one such column has.
Then you should link them together by FK relationships.