从MySQL表读取字符串到Eclipse有问题



我有一个优惠券项目,但我有一个问题,当我试图读取优惠券到Eclipse。我有一个类别表,它与我的优惠券表在"category_id"行相连。这是一个整型。当使用add Method时,我将我的ENUM转换为int,以便将其添加到CATEGORY_ID中,没有问题。

我的问题是当试图读取它时,我尝试将其转换为STRING以获得文本值,但是,我得到一个异常。

这是我的代码:

ENUM类:

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;
}
}

添加优惠券到表coupon的方法:

// 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)我尝试a并将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 (number),则需要一个方法在数字和枚举元素之间进行转换。像这样

//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))

或者需要在表中存储元素的实际名称

你也不应该在你的查询中使用*,"SELECT *…",而是一个列名列表,所以很清楚你在java代码中映射的列,"SELECTCOMPANY_ID,CATEGORY_ID,TITLE,…">

正如我正确理解的那样,您将category存储在coupon中作为代码模型中的enum常量。在将其存储到数据库时,您使用自己提供的方法将其映射为整数值。

罪魁祸首在Category.valueOf(resultSet.getString(3))方法/部分。Enum.valueOf方法是Java提供的枚举的默认方法,它使用String作为参数-可能因此您也使用resultSet.getString(3)而不是resultSet.getInt(3),这将更直观。

从JavaDoc(你可以在这里找到)它说:

…名称必须与用于声明枚举的标识符完全匹配此类型中的常量。(多余的空白字符不会允许的。)…

这意味着要使valueOf方法工作,您需要使用以下值之一作为其参数来调用它:FOOD, ELECTRICITY, RESTAURANT, VACATION, HOTEL。用int值来调用它,比如1,2,…或5将导致你面临的IllegalArgumentException

有两种解决方法:

  • 要么改变你的数据库模型,通过在category值上调用toString方法在表中存储枚举值/常量作为字符串插入到数据库之前(然后你的代码从数据库读取coupons可以保持不变)。

  • 或者您需要提供您自己的自定义实现"valueOf";方法-例如findCategoryById-它将使用整数值作为其参数。通过编写自己的findCategoryById方法,将coupons插入数据库的代码可以保持不变。

要实现自己的findCategoryById,Category枚举中方法的签名应该是这样的:

public static Category findCategoryById(int index)

然后可以通过Category.values()遍历所有可用的常量,并将cat与传递给方法的参数进行比较,并根据它返回匹配的值。

如果没有匹配,您可以简单地返回null或抛出IllegalArgumentException。我个人更喜欢后者,因为它遵循"快速失败"的原则。方法和可以避免讨厌和耗时的搜索错误。


注意:Java中的枚举也有一个自动生成/自动分配的序号。您可以简单地通过调用枚举值的ordinal方法来请求它。在您的例子中,序号与自己分配的cat值相匹配,因此您可以使用它们,而不是自己维护cat属性。

在使用序数时,值得一提的是,在枚举中指定常量的顺序很重要!当你改变常数的顺序,那么序数就会。因此,在使用序数时也需要小心。因此,您可能更愿意坚持当前的方法(它一点也不坏,而且被广泛使用),因为它避免了序数的排序问题。