将字符串从 MySQL table 读取到 Eclipse 时遇到问题
Having trouble reading String from MySQL table to Eclipse
我有一个优惠券项目,但在尝试将优惠券读取到 Eclipse 时遇到问题。我有一个 table 的类别,这些类别与我的优惠券 table 在行“CATEGORY_ID”中是一个整数。使用 add 方法时,我将我的 ENUM 转换为 int 以便毫无问题地将其添加到 CATEGORY_ID。
我的问题是在尝试读取它时,我尝试将其转换为 STRING 以获取文本值,但是,出现异常。
这是我的代码:
枚举CLASS:
public enum Category {
FOOD(1), ELECTRICITY(2), RESTAURANT(3), VACATION(4), HOTEL(5);
private Category(final int cat) {
this.cat = cat;
}
private int cat;
public int getIDX() {
return cat;
}
private Category(String cat1) {
this.cat1 = cat1;
}
private String cat1;
public String getName() {
return cat1;
}
}
将优惠券添加到 table 优惠券的方法:
// sql = "INSERT INTO `couponsystem`.`coupons` (`COMPANY_ID`,`CATEGORY_ID`,`TITLE`, `DESCRIPTION`,
`START_DATE`, `END_DATE`, `AMOUNT`, `PRICE`, `IMAGE`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);";
@Override
public void addCoupon(Coupon coupon) throws SQLException {
Connection connection = pool.getConnection();
try {
PreparedStatement statement = connection.prepareStatement(ADD_COUPON);
statement.setInt(1, coupon.getCompanyID());
statement.setInt(2, coupon.getCategory().getIDX());
statement.setString(3, coupon.getTitle());
statement.setString(4, coupon.getDescription());
statement.setDate(5, (Date) coupon.getStartDate());
statement.setDate(6, (Date) coupon.getEndDate());
statement.setInt(7, coupon.getAmount());
statement.setDouble(8, coupon.getPrice());
statement.setString(9, coupon.getImage());
statement.execute();
} finally {
pool.restoreConnection(connection);
}
}
领取优惠券的方法:
// GET_ONE_COUPON = "SELECT * FROM `couponsystem`.`coupons` WHERE (`id` = ?);";
@Override
public Coupon getOneCoupon(int couponID) throws SQLException {
Connection connection = pool.getConnection();
Coupon result = null;
List<Category> cats = new ArrayList<Category>(EnumSet.allOf(Category.class));
try {
PreparedStatement statement = connection.prepareStatement(GET_ONE_COUPON);
statement.setInt(1, couponID);
ResultSet resultSet = statement.executeQuery();
resultSet.next();
result = new Coupon(resultSet.getInt(1), resultSet.getInt(2), Category.valueOf(resultSet.getString(3)),
resultSet.getString(4), resultSet.getString(5), resultSet.getDate(6), resultSet.getDate(7),
resultSet.getInt(8), resultSet.getDouble(9), resultSet.getString(10));
} finally {
pool.restoreConnection(connection);
}
return result;
在列索引 (3) 上,我尝试将 ENUM 转换为字符串以获取文本值,这是我遇到异常的地方。
异常:
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant coupon.beans.Category.5
at java.base/java.lang.Enum.valueOf(Enum.java:240)
at coupon.beans.Category.valueOf(Category.java:1)
at coupon.dbdao.CouponsDBDAO.getOneCoupon(CouponsDBDAO.java:125)
at coupon.Program.main(Program.java:65)
希望我的问题很清楚。我可以添加更多信息。
valueOf
需要一个与枚举元素名称相对应的字符串,例如“FOOD”,但看起来您传递的是一个数字。如果你想从枚举中传递 id(数字),你需要一种在数字和枚举元素之间进行转换的方法。像这样
//in the enum Category
public static Category categoryFor(int id) {
switch (id) {
case 1:
return FOOD;
case 2:
return ELECTRICITY;
//... more case
default:
return HOTEL;
}
}
然后像这样称呼它
Category.categoryFor(resultSet.getInt(2))
或者您需要在 table.
中存储元素的实际名称
此外,您不应在查询中使用 *、“SELECT * ...”,而应使用列名列表,以便清楚您在 java 代码中映射的列, "SELECT COMPANY_ID
, CATEGORY_ID
,TITLE
,..."
正如我正确理解的那样,您将 category
存储在 coupon
中作为 代码模型 中的枚举常量。在将它存储到数据库时,您正在使用您提供的方法将其映射到一个整数值。
罪魁祸首在 Category.valueOf(resultSet.getString(3))
方法/部分。 Enum.valueOf
方法是 Java
提供的枚举的默认方法,它使用 String
作为参数 - 可能因此您也使用 resultSet.getString(3)
而不是 resultSet.getInt(3)
这会更直观。
从 Java 文档(您可以 find here)它说:
... The name must match exactly an identifier used to declare an enum
constant in this type. (Extraneous whitespace characters are not
permitted.) ...
这意味着要使 valueOf
方法正常工作,您需要使用以下值之一作为参数调用它:食品、电力、餐厅、假期、酒店。使用 1、2、... 或 5 等 int 值调用它会导致您面临 IllegalArgumentException
。
有两种解决方法可以解决这个问题:
通过在 category
值之前调用 toString
方法,更改数据库模型以将枚举值/常量作为字符串存储在 table 中插入数据库(然后你的代码从数据库中读取 coupons
可以保持不变)。
或者您需要提供您自己的“valueOf
”方法的自定义实现 - 例如findCategoryById
- 它将使用整数值作为其参数。通过编写您自己的 findCategoryById
方法,您将 coupons
插入数据库的代码可以保持不变。
要实现您自己的 findCategoryById
Category
枚举中方法的签名应如下所示:
public static Category findCategoryById(int index)
然后您可以通过 Category.values()
遍历所有可用常量,并将 cat
与传递给方法的参数和基于它的匹配值 return 进行比较。
如果 none 匹配,您可以简单地 return null
或者也可以抛出一个 IllegalArgumentException
。我个人更喜欢后者,因为它遵循“快速失败”方法,并且可以避免令人讨厌且耗时的错误搜索。
注意: Java 中的枚举也有一个自动生成/自动分配的序号。您可以通过对枚举的值调用 ordinal
方法来简单地请求它。在您的情况下,序数匹配自分配的 cat
值,因此您可以使用它们,而不是自己维护 cat
属性。
在使用序数时,值得一提的是在枚举中指定常量的顺序很重要!当您更改常量的顺序时,序数也会如此。因此,在使用序数时也需要小心。因此,您可能更愿意坚持使用当前的方法(一点也不差,而且被广泛使用),因为它避免了序数的排序问题。
我有一个优惠券项目,但在尝试将优惠券读取到 Eclipse 时遇到问题。我有一个 table 的类别,这些类别与我的优惠券 table 在行“CATEGORY_ID”中是一个整数。使用 add 方法时,我将我的 ENUM 转换为 int 以便毫无问题地将其添加到 CATEGORY_ID。
我的问题是在尝试读取它时,我尝试将其转换为 STRING 以获取文本值,但是,出现异常。
这是我的代码:
枚举CLASS:
public enum Category {
FOOD(1), ELECTRICITY(2), RESTAURANT(3), VACATION(4), HOTEL(5);
private Category(final int cat) {
this.cat = cat;
}
private int cat;
public int getIDX() {
return cat;
}
private Category(String cat1) {
this.cat1 = cat1;
}
private String cat1;
public String getName() {
return cat1;
}
}
将优惠券添加到 table 优惠券的方法:
// sql = "INSERT INTO `couponsystem`.`coupons` (`COMPANY_ID`,`CATEGORY_ID`,`TITLE`, `DESCRIPTION`,
`START_DATE`, `END_DATE`, `AMOUNT`, `PRICE`, `IMAGE`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);";
@Override
public void addCoupon(Coupon coupon) throws SQLException {
Connection connection = pool.getConnection();
try {
PreparedStatement statement = connection.prepareStatement(ADD_COUPON);
statement.setInt(1, coupon.getCompanyID());
statement.setInt(2, coupon.getCategory().getIDX());
statement.setString(3, coupon.getTitle());
statement.setString(4, coupon.getDescription());
statement.setDate(5, (Date) coupon.getStartDate());
statement.setDate(6, (Date) coupon.getEndDate());
statement.setInt(7, coupon.getAmount());
statement.setDouble(8, coupon.getPrice());
statement.setString(9, coupon.getImage());
statement.execute();
} finally {
pool.restoreConnection(connection);
}
}
领取优惠券的方法:
// GET_ONE_COUPON = "SELECT * FROM `couponsystem`.`coupons` WHERE (`id` = ?);";
@Override
public Coupon getOneCoupon(int couponID) throws SQLException {
Connection connection = pool.getConnection();
Coupon result = null;
List<Category> cats = new ArrayList<Category>(EnumSet.allOf(Category.class));
try {
PreparedStatement statement = connection.prepareStatement(GET_ONE_COUPON);
statement.setInt(1, couponID);
ResultSet resultSet = statement.executeQuery();
resultSet.next();
result = new Coupon(resultSet.getInt(1), resultSet.getInt(2), Category.valueOf(resultSet.getString(3)),
resultSet.getString(4), resultSet.getString(5), resultSet.getDate(6), resultSet.getDate(7),
resultSet.getInt(8), resultSet.getDouble(9), resultSet.getString(10));
} finally {
pool.restoreConnection(connection);
}
return result;
在列索引 (3) 上,我尝试将 ENUM 转换为字符串以获取文本值,这是我遇到异常的地方。
异常:
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant coupon.beans.Category.5
at java.base/java.lang.Enum.valueOf(Enum.java:240)
at coupon.beans.Category.valueOf(Category.java:1)
at coupon.dbdao.CouponsDBDAO.getOneCoupon(CouponsDBDAO.java:125)
at coupon.Program.main(Program.java:65)
希望我的问题很清楚。我可以添加更多信息。
valueOf
需要一个与枚举元素名称相对应的字符串,例如“FOOD”,但看起来您传递的是一个数字。如果你想从枚举中传递 id(数字),你需要一种在数字和枚举元素之间进行转换的方法。像这样
//in the enum Category
public static Category categoryFor(int id) {
switch (id) {
case 1:
return FOOD;
case 2:
return ELECTRICITY;
//... more case
default:
return HOTEL;
}
}
然后像这样称呼它
Category.categoryFor(resultSet.getInt(2))
或者您需要在 table.
中存储元素的实际名称此外,您不应在查询中使用 *、“SELECT * ...”,而应使用列名列表,以便清楚您在 java 代码中映射的列, "SELECT COMPANY_ID
, CATEGORY_ID
,TITLE
,..."
正如我正确理解的那样,您将 category
存储在 coupon
中作为 代码模型 中的枚举常量。在将它存储到数据库时,您正在使用您提供的方法将其映射到一个整数值。
罪魁祸首在 Category.valueOf(resultSet.getString(3))
方法/部分。 Enum.valueOf
方法是 Java
提供的枚举的默认方法,它使用 String
作为参数 - 可能因此您也使用 resultSet.getString(3)
而不是 resultSet.getInt(3)
这会更直观。
从 Java 文档(您可以 find here)它说:
... The name must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.) ...
这意味着要使 valueOf
方法正常工作,您需要使用以下值之一作为参数调用它:食品、电力、餐厅、假期、酒店。使用 1、2、... 或 5 等 int 值调用它会导致您面临 IllegalArgumentException
。
有两种解决方法可以解决这个问题:
通过在
category
值之前调用toString
方法,更改数据库模型以将枚举值/常量作为字符串存储在 table 中插入数据库(然后你的代码从数据库中读取coupons
可以保持不变)。或者您需要提供您自己的“
valueOf
”方法的自定义实现 - 例如findCategoryById
- 它将使用整数值作为其参数。通过编写您自己的findCategoryById
方法,您将coupons
插入数据库的代码可以保持不变。
要实现您自己的 findCategoryById
Category
枚举中方法的签名应如下所示:
public static Category findCategoryById(int index)
然后您可以通过 Category.values()
遍历所有可用常量,并将 cat
与传递给方法的参数和基于它的匹配值 return 进行比较。
如果 none 匹配,您可以简单地 return null
或者也可以抛出一个 IllegalArgumentException
。我个人更喜欢后者,因为它遵循“快速失败”方法,并且可以避免令人讨厌且耗时的错误搜索。
注意: Java 中的枚举也有一个自动生成/自动分配的序号。您可以通过对枚举的值调用 ordinal
方法来简单地请求它。在您的情况下,序数匹配自分配的 cat
值,因此您可以使用它们,而不是自己维护 cat
属性。
在使用序数时,值得一提的是在枚举中指定常量的顺序很重要!当您更改常量的顺序时,序数也会如此。因此,在使用序数时也需要小心。因此,您可能更愿意坚持使用当前的方法(一点也不差,而且被广泛使用),因为它避免了序数的排序问题。