Java 如何以编程方式为 BIRT 报告设置数据源?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3244468/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set a datasource for a BIRT report programmatically?
提问by Mauli
I have a BIRT report which connects to our test database. In the productive environment I would like to supply a datasource which is provided by the container through jndi.
我有一个连接到我们的测试数据库的 BIRT 报告。在生产环境中,我想提供一个由容器通过 jndi 提供的数据源。
How would I set the datasource programmatically for the given report?
我将如何以编程方式为给定报告设置数据源?
...
IReportRunnable design = birtEngine.openReportDesign ( new File ( properties.getProperty ( "reportPath" ), report + ".rptdesign" ).getAbsolutePath () );
IRunAndRenderTask task = birtEngine.createRunAndRenderTask ( design );
PDFRenderOption options = new PDFRenderOption ();
options.setOutputFormat ( PDFRenderOption.OUTPUT_FORMAT_PDF );
options.setOutputStream ( out );
task.setRenderOption ( options );
for ( Entry<String, Object> entry : parameters.entrySet () )
{
task.setParameterValue ( entry.getKey (), entry.getValue () );
}
task.run ();
task.close ();
...
I guess I would have to modify the design
but on the other hand task
has a method setDataSource
but that looks a bit like I would have to supply some xml dom elements.
我想我将不得不修改design
但另一方面task
有一个方法,setDataSource
但这看起来有点像我必须提供一些 xml dom 元素。
回答by MystikSpiral
Setting just the data source at run-time will be problematic because the data set is bound to a single data source and your controls on the report are then bound to a specific data set. This hierarchy would be pretty sticky to try and build yourself each time the report runs.
在运行时只设置数据源会出现问题,因为数据集绑定到单个数据源,然后报表上的控件绑定到特定数据集。每次运行报告时尝试构建自己的层次结构将非常棘手。
You can parameterize all aspects of the Data Source definition making your design portable through all environments. When editing your Data Source, look at the Property Binding grouping on the left hand side. This should give you ample flexibility to make your data source more portable. You can specify run-time parameters for JDBC URL elements or a run-time JNDI profile.
您可以参数化数据源定义的所有方面,使您的设计可在所有环境中移植。编辑数据源时,请查看左侧的属性绑定分组。这应该为您提供足够的灵活性,使您的数据源更具可移植性。您可以为 JDBC URL 元素或运行时 JNDI 配置文件指定运行时参数。
Hope this helps.
希望这可以帮助。
回答by Adam Morris
You can create a Report Parameter for the database connection string.
您可以为数据库连接字符串创建报告参数。
Then, set the JNDI URL under Data Source -> Property Binding -> JNDI URL, as: params["Database"].value
(Where "Database" is the name of the report parameter)
然后,在Data Source -> Property Binding -> JNDI URL下设置JNDI URL,为:params["Database"].value
(其中"Database"是报表参数的名称)
回答by Husmukh
Look at following code you may get some help in providing data source at runtime.
查看以下代码,您可能会在运行时提供数据源方面获得一些帮助。
For my requirements it works fine.
对于我的要求,它工作正常。
I got this from some site do not remember.
我是从某个网站上得到的,不记得了。
import java.io.IOException;
import java.util.ArrayList;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.report.model.api.CellHandle;
import org.eclipse.birt.report.model.api.DataItemHandle;
import org.eclipse.birt.report.model.api.DesignConfig;
import org.eclipse.birt.report.model.api.ElementFactory;
import org.eclipse.birt.report.model.api.IDesignEngine;
import org.eclipse.birt.report.model.api.IDesignEngineFactory;
import org.eclipse.birt.report.model.api.LabelHandle;
import org.eclipse.birt.report.model.api.OdaDataSetHandle;
import org.eclipse.birt.report.model.api.OdaDataSourceHandle;
import org.eclipse.birt.report.model.api.PropertyHandle;
import org.eclipse.birt.report.model.api.ReportDesignHandle;
import org.eclipse.birt.report.model.api.RowHandle;
import org.eclipse.birt.report.model.api.SessionHandle;
import org.eclipse.birt.report.model.api.StructureFactory;
import org.eclipse.birt.report.model.api.TableHandle;
import org.eclipse.birt.report.model.api.activity.SemanticException;
import org.eclipse.birt.report.model.api.elements.structures.ComputedColumn;
import com.ibm.icu.util.ULocale;
/**
* Dynamic Table BIRT Design Engine API (DEAPI) demo.
*/
public class DECreateDynamicTable
{
ReportDesignHandle designHandle = null;
ElementFactory designFactory = null;
StructureFactory structFactory = null;
public static void main( String[] args )
{
try
{
DECreateDynamicTable de = new DECreateDynamicTable();
ArrayList al = new ArrayList();
al.add("USERNAME");
al.add("COUNTRY");
de.buildReport(al, "From GTM_REPORT_APP_USER" );
}
catch ( IOException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch ( SemanticException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
void buildDataSource( ) throws SemanticException
{
OdaDataSourceHandle dsHandle = designFactory.newOdaDataSource(
"Data Source", "org.eclipse.birt.report.data.oda.jdbc" );
dsHandle.setProperty( "odaDriverClass",
"oracle.jdbc.driver.OracleDriver" );
dsHandle.setProperty( "odaURL", "jdbc:oracle:thin:@xeon:1521:ora9i" );
dsHandle.setProperty( "odaUser", "AIMS_GTMNE" );
dsHandle.setProperty( "odaPassword", "AIMS_GTMNE" );
designHandle.getDataSources( ).add( dsHandle );
}
void buildDataSet(ArrayList cols, String fromClause ) throws SemanticException
{
OdaDataSetHandle dsHandle = designFactory.newOdaDataSet( "ds",
"org.eclipse.birt.report.data.oda.jdbc.JdbcSelectDataSet" );
dsHandle.setDataSource( "Data Source" );
String qry = "Select ";
for( int i=0; i < cols.size(); i++){
qry += " " + cols.get(i);
if( i != (cols.size() -1) ){
qry += ",";
}
}
qry += " " + fromClause;
dsHandle.setQueryText( qry );
designHandle.getDataSets( ).add( dsHandle );
}
void buildReport(ArrayList cols, String fromClause ) throws IOException, SemanticException
{
//Configure the Engine and start the Platform
DesignConfig config = new DesignConfig( );
config.setProperty("BIRT_HOME", "D:/Softwares/Frame Works - APIs-Tools/birt-runtime-2_6_1/birt-runtime-2_6_1/ReportEngine");
IDesignEngine engine = null;
try{
Platform.startup( config );
IDesignEngineFactory factory = (IDesignEngineFactory) Platform.createFactoryObject( IDesignEngineFactory.EXTENSION_DESIGN_ENGINE_FACTORY );
engine = factory.createDesignEngine( config );
}catch( Exception ex){
ex.printStackTrace();
}
SessionHandle session = engine.newSessionHandle( ULocale.ENGLISH ) ;
try{
//open a design or a template
designHandle = session.openDesign("D:/tempBirtReport/test.rptdesign");
designFactory = designHandle.getElementFactory( );
buildDataSource();
buildDataSet(cols, fromClause);
TableHandle table = designFactory.newTableItem( "table", cols.size() );
table.setWidth( "100%" );
table.setDataSet( designHandle.findDataSet( "ds" ) );
PropertyHandle computedSet = table.getColumnBindings( );
ComputedColumn cs1 = null;
for( int i=0; i < cols.size(); i++){
cs1 = StructureFactory.createComputedColumn();
cs1.setName((String)cols.get(i));
cs1.setExpression("dataSetRow[\"" + (String)cols.get(i) + "\"]");
computedSet.addItem(cs1);
}
// table header
RowHandle tableheader = (RowHandle) table.getHeader( ).get( 0 );
for( int i=0; i < cols.size(); i++){
LabelHandle label1 = designFactory.newLabel( (String)cols.get(i) );
label1.setText((String)cols.get(i));
CellHandle cell = (CellHandle) tableheader.getCells( ).get( i );
cell.getContent( ).add( label1 );
}
// table detail
RowHandle tabledetail = (RowHandle) table.getDetail( ).get( 0 );
for( int i=0; i < cols.size(); i++){
CellHandle cell = (CellHandle) tabledetail.getCells( ).get( i );
DataItemHandle data = designFactory.newDataItem( "data_"+(String)cols.get(i) );
data.setResultSetColumn( (String)cols.get(i));
cell.getContent( ).add( data );
}
designHandle.getBody( ).add( table );
// Save the design and close it.
designHandle.saveAs( "D:/tempBirtReport/test.rptdesign" ); //$NON-NLS-1$
designHandle.close( );
System.out.println("Finished");
}catch (Exception e){
e.printStackTrace();
}
}
}
回答by hvb
I like Adams approach. Here's how we do it:
我喜欢亚当斯的方法。这是我们如何做到的:
/*
* Change the data sources in the .rptdesign
*/
void changeDataSource(ElementFactory designFactory,
ReportDesignHandle designHandle, String userConnect)
throws SemanticException {
SlotHandle datasources = designHandle.getDataSources();
SlotIterator iter = (SlotIterator) datasources.iterator();
while (iter.hasNext()) {
DesignElementHandle dsHandle = (DesignElementHandle) iter.next();
if (dsHandle instanceof OdaDataSourceHandle && dsHandle.getName().equals("lisa")) {
log.debug("changeDataSource: Changing datasource "
+ dsHandle.getName() + " new url=" + getLisaDbUrl());
dsHandle.setProperty("odaDriverClass",
"oracle.jdbc.driver.OracleDriver");
dsHandle.setProperty("odaURL", getLisaDbUrl());
dsHandle.setProperty("odaUser", getLisaUser());
dsHandle.setProperty("odaPassword", getLisaPassword());
} else {
log.debug("changeDataSource: Ignoring DS " + dsHandle.getName());
}
}
}
Here, "lisa" ist he name of the datasource we would like to change at runtime. The get... function return the values needed at "production" run time.
此处,“lisa”是我们希望在运行时更改的数据源的名称。get... 函数返回“生产”运行时所需的值。
回答by Sasi
This worked for me. I got the context and from context got the dataSource and passed the connection to Birt report like below
这对我有用。我得到了上下文并从上下文中得到了数据源并将连接传递给如下所示的 Birt 报告
Context initialContext = new InitialContext();
if ( initialContext == null){
System.out.println("JNDI problem. Cannot get InitialContext.");
}
DataSource datasource = (DataSource)initialContext.lookup("java:/datasources/SAMPLE");
task.getAppContext().put("OdaJDBCDriverPassInConnection", datasource.getConnection());