Запрос JDBC + Scanner.next() дает исключение InputMismatchException
Я написал простейшую реализацию СУБД с использованием JDBC Java. В моем приложении я предоставляю пользователям возможность выполнять CRUD-операции над простой базой данных mysql. Все сделано в консоли. Проблема в том, что когда пользователь выбирает операцию из меню (запросы в настоящее время жестко заданы), а затем предоставляет запрос java.util.InputMismatchException
исключение брошено. Есть идеи, почему это может происходить? Вот код:
import java.sql.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Base base = new Base();
boolean result = false;
try{
base.connect();
}catch(SQLException se){
se.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
Scanner sc = new Scanner(System.in);
int menuChoice = -1;
String query = "";
while(menuChoice != 0){
showMenu();
menuChoice = sc.nextInt();
System.out.println("Please provide your query : ");
switch(menuChoice){
case 1:
query = sc.next();
result = base.insert(query);
break;
case 2:
query = sc.next();
result = base.update(query);
break;
case 3:
query = sc.next();
result = base.retrieve(query);
break;
case 4:
query = sc.next();
result = base.delete(query);
break;
case 0:
System.out.println("Bye bye");
base.connection = null;
System.exit(0);
}
}
}
public static void showMenu(){
System.out.println("Welcome to simple JDBC example application./n");
System.out.println("Choose desired operation:\n\n");
System.out.println("1. Insert new instance");
System.out.println("2. Update existing instance");
System.out.println("3. Lookup");
System.out.println("4. Delete instance");
System.out.println("0. Exit");
System.out.print("\n\n Select: ");
}
}
class Base {
private String username = "";
private String password = "";
private String dbname = "";
private String servername = "";
private Statement stmt = null;
Connection connection = null;
public Base(){
}
public boolean create(){
return true;
}
public void connect() throws Exception{
String driverName = "com.mysql.jdbc.Driver";
Class.forName(driverName);
String url = "jdbc:mysql://" + servername + "/" + dbname;
connection = DriverManager.getConnection(url, username, password);
stmt = connection.createStatement();
}
public boolean insert(String statement){
try{
int i=stmt.executeUpdate(statement);
System.out.println("Successfully inserted.");
return true;
}catch(SQLException se){
System.out.println("Inserting data failed.");
return false;
}
}
public boolean update(String statement){
try{
int i=stmt.executeUpdate(statement);
System.out.println("Successfully updated.");
return true;
}catch(SQLException se){
System.out.println("Updating data failed.");
return false;
}
}
public boolean retrieve(String query){
try{
ResultSet rs = stmt.executeQuery(query);
System.out.println("Successfully retrieved :");
while (rs.next()){
System.out.println(rs.getRow()+". "+rs.toString());
}
return true;
}catch(SQLException se){
System.out.println("Updating data failed.");
return false;
}
}
public boolean delete(String statement){
try{
int i=stmt.executeUpdate(statement);
System.out.println("Successfully deleted.");
return true;
}catch(SQLException se){
System.out.println("Deleting data failed.");
return false;
}
}
}
/*
CREATE TABLE users (
user_login varchar(10) PRIMARY KEY NOT NULL,
user_password varchar(20) NOT NULL
);
CREATE TABLE groups (
group_id varchar(10) PRIMARY KEY NOT NULL,
group_name varchar(50),
group_description varchar(200)
);
CREATE TABLE groups_users (
user_login varchar(10),
group_id varchar(10),
FOREIGN KEY (user_login) REFERENCES users(user_login),
FOREIGN KEY (group_id) REFERENCES groups(group_id));
*/
РЕДАКТИРОВАТЬ: Traceback
Select: 1
Please provide your query :
SELECT * FROM users
Inserting data failed.
Welcome to simple JDBC example application./n
Choose desired operation:
Exception in thread "main" java.util.InputMismatchException
1. Insert new instance
at java.util.Scanner.throwFor(Scanner.java:840)
2. Update existing instance
at java.util.Scanner.next(Scanner.java:1461)
3. Lookup
at java.util.Scanner.nextInt(Scanner.java:2091)
4. Delete instance
0. Exit
at java.util.Scanner.nextInt(Scanner.java:2050)
at task.Main.main(Main.java:26)
Select: Java Result: 1
так что ошибка исходит из строки menuChoice = sc.nextInt();
, Более того, когда я добавил еще один экземпляр сканера только для запросов, тип операции выбора возвращает пользователя обратно в меню без запроса запроса.
2 ответа
Вот определение InputMismatchException:
Выдается сканером, чтобы указать, что полученный токен не соответствует шаблону для ожидаемого типа или что токен находится вне диапазона ожидаемого типа.
Я отсканировал ваш код, и кажется, menuChoice = sc.nextInt();
может быть тот, который выбрасывает это исключение. Ваши шансы while loop
зацикливается слишком много раз, и у вашего сканера нет следующего значения int для чтения, поэтому вы получаете это исключение.
nextInt()
это единственный API сканера, который вы использовали, который вызывает это конкретное исключение. Вот документация nextInt (): -
public int nextInt(int radix)
Scans the next token of the input as an int. This method will throw InputMismatchException if the next token cannot be translated into a valid int value as described below. If the translation is successful, the scanner advances past the input that matched.
If the next token matches the Integer regular expression defined above then the token is converted into an int value as if by removing all locale specific prefixes, group separators, and locale specific suffixes, then mapping non-ASCII digits into ASCII digits via Character.digit, prepending a negative sign (-) if the locale specific negative prefixes and suffixes were present, and passing the resulting string to Integer.parseInt with the specified radix.
Parameters:
radix - the radix used to interpret the token as an int value
Returns:
the int scanned from the input
Throws:
InputMismatchException - if the next token does not match the Integer regular expression, or is out of range
NoSuchElementException - if input is exhausted
IllegalStateException - if this scanner is closed
РЕДАКТИРОВАТЬ:
Попробуйте изменить цикл while следующим образом:
while(menuChoice != 0 && sc.hasNext()){
...
}
Это должно исправить вашу проблему.
Ваш Scanner
ломает токены на пустом пространстве. Scanner.next()
возвращает только один токен (например, "SELECT"). Оставшаяся часть введенного вами запроса доступна для сканирования для вашего nextInt()
вызовите, но следующий токен в вашем запросе (например, "*") не является целым числом.
Вместо next()
ты наверное хочешь nextLine()
,