I'm getting the following error when trying to execute statemet.executeUpdate()
in my code:
Local variable statement defined in an enclosing scope must be final or effectively final.
This is my code so far:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement;. import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; public class a1 { protected Shell shell; private Text text; private Text text_1; private Text text_2; private Text text_3; /** * Launch the application. * @param args */ public static void main(String[] args) { try { a1 window = new a1(); window.open(); } catch (Exception e) { e.printStackTrace(); } } /** * Open the window. */ public void open() { Display display = Display.getDefault(); createContents(); shell.open(); shell.layout(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } /** * Create contents of the window. */ protected void createContents() { Connection connect = null; ResultSet resultSet = null; try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { connect = DriverManager.getConnection("jdbc:mysql://localhost/railwaydb", "root", ""); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } Statement statement = null; // statements allow to issue SQL queries to the database try { statement = connect.createStatement(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } shell = new Shell(); shell.setSize(450, 300); shell.setText("SWT Application"); Label lblName = new Label(shell, SWT.NONE); lblName.setBounds(10, 43, 47, 15); lblName.setText("Name"); Label lblFrom = new Label(shell, SWT.NONE); lblFrom.setBounds(10, 74, 55, 15); lblFrom.setText("From"); Label lblTo = new Label(shell, SWT.NONE); lblTo.setBounds(10, 105, 55, 15); lblTo.setText("To"); Label lblPrice = new Label(shell, SWT.NONE); lblPrice.setBounds(10, 137, 55, 15); lblPrice.setText("Price"); text = new Text(shell, SWT.BORDER); text.setBounds(64, 43, 76, 21); text_1 = new Text(shell, SWT.BORDER); text_1.setBounds(64, 74, 76, 21); text_2 = new Text(shell, SWT.BORDER); text_2.setBounds(64, 105, 76, 21); text_3 = new Text(shell, SWT.BORDER); text_3.setBounds(64, 137, 76, 21); Label lblRailwayDatabase = new Label(shell, SWT.NONE); lblRailwayDatabase.setBounds(174, 10, 97, 15); lblRailwayDatabase.setText("Railway Database"); Label lblCreateView = new Label(shell, SWT.NONE); lblCreateView.setBounds(189, 43, 76, 15); lblCreateView.setText("Create View"); Button btnName = new Button(shell, SWT.CHECK); btnName.setBounds(189, 73, 93, 16); btnName.setText("Name"); Button btnFrom = new Button(shell, SWT.CHECK); btnFrom.setBounds(189, 105, 93, 16); btnFrom.setText("From"); Button btnTo = new Button(shell, SWT.CHECK); btnTo.setBounds(189, 137, 93, 16); btnTo.setText("To"); Button btnPrice = new Button(shell, SWT.CHECK); btnPrice.setBounds(189, 171, 93, 16); btnPrice.setText("Price"); Button btnInsert = new Button(shell, SWT.NONE); btnInsert.addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { String name = text.getText(); String from = text_1.getText(); String to = text_2.getText(); String price = text_3.getText(); String query = "INSERT INTO booking (name, fromst, tost, price) VALUES ('"+name+"', '"+from+"', '"+to+"', '"+price+"')"; try { statement.executeUpdate(query); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } }); btnInsert.setBounds(10, 171, 75, 25); btnInsert.setText("Insert"); Button btnView = new Button(shell, SWT.NONE); btnView.setBounds(307, 74, 75, 25); btnView.setText("View"); Button btnIndex = new Button(shell, SWT.NONE); btnIndex.setBounds(307, 127, 75, 25); btnIndex.setText("Index"); } }
I also tried to set statement
final but the declaration gives me another error.
There are several problems with local variables declared in too large scopes. One is that the variable may be declared but never used, as is the case if someCondition in the above example is false. Since declarations of variables in many cases costs computational cycles, you may end up wasting time for nothing.
If the value had been changed, the exception Local variable name defined in an enclosing scope must be final or effectively final would have been thrown. The work around is to create a new list and assign the local variable in it. The value can be modified either within or outside the lamda expression in the list.
A scope is a region of the program and broadly speaking there are three places, where variables can be declared: Inside a function or a block which is called local variables, In the definition of function parameters which is called formal parameters.
You have a scope problem indeed, because statement
is a local method variable defined here:
protected void createContents() { ... Statement statement = null; // local variable ... btnInsert.addMouseListener(new MouseAdapter() { // anonymous inner class @Override public void mouseDown(MouseEvent e) { ... try { statement.executeUpdate(query); // local variable out of scope here } catch (SQLException e1) { e1.printStackTrace(); } ... }); }
When you try to access this variable inside mouseDown()
method you are trying to access a local variable from within an anonymous inner class and the scope is not enough. So it definitely must be final
(which given your code is not possible) or declared as a class member so the inner class can access this statement
variable.
Sources:
Make statement
a class member instead of a local variable:
public class A1 { // Note Java Code Convention, also class name should be meaningful private Statement statement; ... }
Define another final variable and use this one instead, as suggested by @HotLicks:
protected void createContents() { ... Statement statement = null; try { statement = connect.createStatement(); final Statement innerStatement = statement; } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } ... }
Reconsider your approach. If statement
variable won't be used until btnInsert
button is pressed then it doesn't make sense to create a connection before this actually happens. You could use all local variables like this:
btnInsert.addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { try { Class.forName("com.mysql.jdbc.Driver"); try (Connection connect = DriverManager.getConnection(...); Statement statement = connect.createStatement()) { // execute the statement here } catch (SQLException ex) { ex.printStackTrace(); } } catch (ClassNotFoundException ex) { e.printStackTrace(); } });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With