问题描述
首先,我将向您解释我要去做的事情,而不是我为到达那里所做的事情。
我有一个Amazon RDS实例,并且正在使用Spring + JPA与之交互。在该数据库中,有一个称为“产品”的表。以前,我只是将存储的货币用作数据库中的INT,存储分并在Java中进行转换,效果很好。我一直在尝试使用数据库中的DECIMAL(13,2)类型作为货币,并在Java端使用joda.money.Money稍微清理一下代码。餐桌产品的“货币”列的定义如下所示:
@Column(name = "prodprice",columnDeFinition = "DECIMAL(13,2)")
@Type(type = "org.joda.money.Money",parameters = {@org.hibernate.annotations.Parameter(name = "currencyCode",value = "CAD")})
private Money prodPrice;
我还有另一个名为flower的实体,其货币是这样定义的
@JsonSerialize(using = MoneySerializer.class)
@JsonDeserialize(using = MoneyDeserializer.class)
@Column(name = "priceperpound")
@Type(type = "org.joda.money.Money",value = "CAD")})
private Money pricePerPound;
此实体通过此方法传递给Spring
@PostMapping("/inventory/addproduct/flower")
@Transactional
public ResponseEntity<?> addFlower(
@RequestBody flower newFlower,@RequestParam String prodName,@RequestParam Integer qtyOnHand,@RequestParam BigDecimal prodPrice,@RequestParam String prodDescription)
{
Integer newProductID = addNewProduct(prodName,qtyOnHand,Money.of(CurrencyUnit.CAD,prodPrice),prodDescription);
newFlower.setProdID(newProductID);
saveEntity(newFlower);
return ResponseEntity.ok(String.format("Product Added.\n ID : %s",newProductID));
}
问题在于,休眠时在生成插入语句时将产品实体中的Money实例视为VARBINARY而不是DECIMAL。我通过调试准备好的语句发现了这一点。该语句显示为:
insert
into
product
(proddescription,prodname,prodprice,prodqtyonhand)
values
(?,?,?)
2020-09-16 16:18:26.172 TRACE 16576 --- [nio-8080-exec-2] o.h.type.descriptor.sql.BasicBinder :
binding parameter [1] as [VARCHAR] - [Decimal Flower Test]
2020-09-16 16:18:26.173 TRACE 16576 --- [nio-8080-exec-2] o.h.type.descriptor.sql.BasicBinder :
binding parameter [2] as [VARCHAR] - [test3]
2020-09-16 16:18:26.174 TRACE 16576 --- [nio-8080-exec-2] o.h.type.descriptor.sql.BasicBinder :
binding parameter [3] as [VARBINARY] - [CAD 10.25]
2020-09-16 16:18:26.175 TRACE 16576 --- [nio-8080-exec-2] o.h.type.descriptor.sql.BasicBinder :
binding parameter [4] as [INTEGER] - [58]
2020-09-16 16:18:26.359 WARN 16576 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.sqlExceptionHelper :
sql Error: 1264,sqlState: 22001
2020-09-16 16:18:26.360 ERROR 16576 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.sqlExceptionHelper :
Data truncation: Out of range value for column 'prodPrice' at row 1
我一步步完成了序列化器类,在花实体中处理Money类似乎没有问题。
我尝试过的事情: 将在花实体中找到的相同注释添加到产品实体, 通过尝试使用double来更改从@RequestParam创建Money实例的方式,甚至可以从String(Money.parse(prodPrice))解析Money。最后,休眠似乎总是将货币单位放在实际值的前面,这就是为什么休眠将其视为VARBINARY的原因。令我特别想到的是
o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [VARBINARY] - [CAD 10.25]
因为它声明的是10.25加元,而不是10.25加元
以前,我也尝试过为休眠设置自己的自定义类型,但我不想走这条路。在这一点上,我对joda.money的信任远胜于我。我应该指出,这是我与Spring JPA进行深度合作的第一次尝试,但我仍然耳熟能详。我使用的MoneySerializer和MoneyDeserializer来自gist.github,您可以通过搜索找到它 gist.github.com上的MoneyDeserializer.java, 两者均由stickfigure发布。
下面是一些有用的摘要
-application.properties
spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:MysqL://DELETEDFORSecurity
spring.datasource.username=DELETEDFORSecurity
spring.datasource.password=DELETEDFORSecurity
logging.level.org.hibernate.sql=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
spring.jpa.properties.hibernate.format_sql=true
-pom.xml依赖项
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.2</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>org.joda</groupId>
<artifactId>joda-money</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.joda</groupId>
<artifactId>joda-convert</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>MysqL</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180130</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
-方法addNewProduct
private Integer addNewProduct(String productName,Integer qtyOnHand,Money prodPrice,String prodDesc)
{
Product newProd = buildNewProduct(productName,prodPrice,prodDesc);
saveEntity(newProd);
return newProd.getProdID();
}
-方法buildNewProduct
private Product buildNewProduct(String productName,String prodDesc)
{
return new Product(productName,prodDesc);
}
-方法saveEntity
private void saveEntity(Object obj)
{
entityManager.persist(obj);
}
如何使用JPA和joda.money将这个值作为DECIMAL(13,2)存储到数据库中? 更好的问题:我在做什么错,从根本上我会误解什么,这个想法有多愚蠢?有更好的方法吗?
此代码没有任何生产能力,我只是想学习。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)