杰瑞科技汇

oracle number java

Of course! This is a very common and important topic when working with Java applications that connect to an Oracle database. The NUMBER data type in Oracle is highly flexible, and mapping it correctly to Java types is crucial for data integrity and application performance.

oracle number java-图1
(图片来源网络,侵删)

Here’s a comprehensive guide covering everything from the basics to best practices.


Understanding the Oracle NUMBER Data Type

First, it's essential to understand what Oracle's NUMBER type is. It's a highly flexible numeric data type that can store zero, positive, and negative numbers with a precision of up to 38 digits.

The general syntax is: NUMBER(precision, scale)

  • Precision: The total number of digits. It can range from 1 to 38. If you omit it, the precision is up to 38 digits.
  • Scale: The number of digits to the right of the decimal point. It can range from -84 to 127.

Here are the most common use cases:

oracle number java-图2
(图片来源网络,侵删)
Declaration Description Example Value
NUMBER A floating-point number with up to 38 digits of precision. 12345678901234567890123456789012345678
NUMBER(p) A fixed-point integer with p digits. NUMBER(10) can store 1234567890
NUMBER(p, s) A fixed-point number with p total digits and s after the decimal. NUMBER(5, 2) can store 45
NUMBER(*, s) A floating-point number with a fixed scale s. NUMBER(*, 2) can store 12
NUMBER(38) A 38-digit integer. Often used for large IDs or counts. 99999999999999999999999999999999999999

The Standard JDBC Way: java.math.BigDecimal

When you use standard JDBC (Java Database Connectivity), the Oracle JDBC driver maps the NUMBER type to java.math.BigDecimal.

This is the most important rule to remember:

Oracle NUMBER ⇔ Java java.math.BigDecimal

Why BigDecimal?

  • Precision: Unlike float or double, BigDecimal can represent numbers with exact precision, which is critical for financial data, currency, and any number where rounding errors are unacceptable.
  • Scale: It can handle the scale specified in the NUMBER(p, s) type correctly.

Example using JDBC (The Old Way)

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JdbcNumberExample {
    public static void main(String[] args) {
        String url = "jdbc:oracle:thin:@localhost:1521:ORCLCDB";
        String user = "your_username";
        String password = "your_password";
        // SQL with a NUMBER column
        String sql = "SELECT product_id, price, quantity_in_stock FROM products";
        try (Connection conn = DriverManager.getConnection(url, user, password);
             PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) {
            while (rs.next()) {
                // Get the ID (likely NUMBER(10))
                int id = rs.getInt("product_id"); // Works for small integers
                // Get the price (likely NUMBER(10, 2))
                BigDecimal price = rs.getBigDecimal("price"); // BEST PRACTICE
                // Get the quantity (likely NUMBER(10))
                long quantity = rs.getLong("quantity_in_stock"); // Works for large integers
                System.out.println("ID: " + id + ", Price: " + price + ", Qty: " + quantity);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Using JPA / Hibernate (The Modern ORM Way)

When you use an Object-Relational Mapping (ORM) framework like JPA with Hibernate, you have more flexibility in choosing your Java types. The ORM will handle the conversion to BigDecimal internally.

oracle number java-图3
(图片来源网络,侵删)

Here are the common Java types you can map to an Oracle NUMBER column in your JPA entity.

Scenario 1: Exact Numbers (Currency, Financial Data)

This is the most important case. You should always use BigDecimal for monetary values.

import javax.persistence.*;
import java.math.BigDecimal;
@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    // Best practice for currency or precise decimal numbers
    @Column(name = "price", precision = 10, scale = 2)
    private BigDecimal price;
    // Getters and Setters...
}

Scenario 2: Integers (No Decimal Part)

If your NUMBER column is guaranteed to be an integer (e.g., NUMBER(10)), you can use the appropriate Java integer type. This is more convenient and type-safe.

Oracle Type Java Type Notes
NUMBER(2) byte For small numbers (-128 to 127)
NUMBER(5) short For small to medium numbers
NUMBER(9) int Most common for IDs, flags, etc.
NUMBER(18) long For large numbers that fit in a long
NUMBER(19) or larger java.math.BigInteger For very large integers
@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // Using int for a status flag (e.g., 0=PENDING, 1=SHIPPED)
    private int status;
    // Using long for a large order number
    private long orderNumber;
    // Getters and Setters...
}

Scenario 3: Approximate Numbers (Scientific Data)

If the precision is not critical and the number can have a very wide range (e.g., scientific notation), you can use double. Be aware of potential rounding errors.

@Entity
public class SensorReading {
    @Id
    private Long id;
    // Using double for a measurement where precision is not 100% critical
    private double temperature;
    // Getters and Setters...
}

Using jOOQ (The Modern SQL DSL Way)

jOOQ is a popular library for writing type-safe SQL queries in Java. It provides excellent support for Oracle's NUMBER type.

jOOQ strongly encourages the use of BigDecimal for all NUMBER types to maintain precision.

import org.jooq.DSLContext;
import org.jooq.impl.DSL;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import static org.jooq.impl.DSL.name; // For table/column names
public class JooqNumberExample {
    public static void main(String[] args) {
        String url = "jdbc:oracle:thin:@localhost:1521:ORCLCDB";
        String user = "your_username";
        String password = "your_password";
        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            DSLContext dsl = DSL.using(conn);
            // jOOQ maps NUMBER to BigDecimal by default
            BigDecimal price = dsl.select(DSL.field("price", BigDecimal.class))
                                  .from(name("products"))
                                  .where(name("product_id").eq(101))
                                  .fetchOne()
                                  .value1();
            System.out.println("The price is: " + price);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Summary and Best Practices

Oracle NUMBER Column Recommended Java Type Why?
NUMBER(p, s) (with s > 0) java.math.BigDecimal The only correct choice. Guarantees precision and scale, essential for financial data.
NUMBER(p) (integer, fits in int) int Convenient, type-safe, and avoids the overhead of BigDecimal. Use for IDs, flags, counts.
NUMBER(p) (integer, fits in long) long Same as above, for larger integer values.
NUMBER(p) (very large integer) java.math.BigInteger For integers that exceed the capacity of a long.
NUMBER (floating point, approximate) double Use with caution. Acceptable for scientific data where minor precision loss is acceptable. Avoid for money.

Quick Decision Flowchart

Is the column an integer? (no decimal part)
  |
  +-- YES --> Does it fit in an `int` (up to ~2 billion)?
  |            |
  |            +-- YES --> Use `int`.
  |            |
  |            +-- NO  --> Does it fit in a `long`?
  |                     |
  |                     +-- YES --> Use `long`.
  |                     |
  |                     +-- NO  --> Use `BigInteger`.
  |
  +-- NO (it has a decimal part) --> Use `BigDecimal`.

By following these guidelines, you'll ensure that your Java application handles Oracle numeric data accurately and efficiently.

分享:
扫描分享到社交APP
上一篇
下一篇