我有一个用例,我在BigDecimal周围编写了一个包装器。我想在数据库中保留/从中获取它。这是我的实体类的样子: -
@Data
@Entity
@Table(name = "transaction_line_item_value")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TypeDefs({
@TypeDef(name = "rupee-custom", defaultForType = Rupee.class, typeClass = RupeeType.class)
})
public class TransactionLineItemValue {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@PodamExclude
private int id;
//@Column(name = "amount", nullable = false) Works! But makes amount immutable.
@Column(name = "amount")
private Rupee amount;
}
目前,Rupee类只不过是BigDecimal的包装器。
RupeeType扩展了AbstractSingleColumnStandardBasicType。它看起来像这样。
public class RupeeType extends AbstractSingleColumnStandardBasicType<BigDecimal> {
public RupeeType() {
super(new RupeeTypeDescriptor(), BigDecimalTypeDescriptor.INSTANCE);
}
@Override
public String getName() {
return "rupee-custom";
}
public static class RupeeTypeDescriptor implements SqlTypeDescriptor {
@Override
public int getSqlType() {
return Types.DOUBLE;
}
@Override
public boolean canBeRemapped() {
return false;
}
@Override
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>(javaTypeDescriptor, (SqlTypeDescriptor) this) {
@Override
protected void doBind(PreparedStatement preparedStatement, X x, int i, WrapperOptions wrapperOptions) throws SQLException {
preparedStatement.setBigDecimal(i, ((Rupee) x).getAmount());
}
@Override
protected void doBind(CallableStatement callableStatement, X x, String s, WrapperOptions wrapperOptions) throws SQLException {
callableStatement.setBigDecimal(s, ((Rupee) x).getAmount());
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicExtractor<X>(javaTypeDescriptor, (SqlTypeDescriptor) this) {
@Override
protected X doExtract(ResultSet resultSet, String s, WrapperOptions wrapperOptions) throws SQLException {
return (X) Rupee.builder().amount(resultSet.getBigDecimal(s)).build();
}
@Override
protected X doExtract(CallableStatement callableStatement, int i, WrapperOptions wrapperOptions) throws SQLException {
return (X) Rupee.builder().amount(callableStatement.getBigDecimal(i)).build();
}
@Override
protected X doExtract(CallableStatement callableStatement, String s, WrapperOptions wrapperOptions) throws SQLException {
return (X) Rupee.builder().amount(callableStatement.getBigDecimal(s)).build();
}
};
}
}
}
这在@UnitOfWork中设置'transactional = false'时有效。如何使用'transactional = true'并且不使用'nullable = false'。
我在Dropwizard中使用Hibernate。
我得到的错误是: -
ERROR [2017-01-12 10:27:50,526] io.dropwizard.jersey.errors.LoggingExceptionMapper: Error handling a request: 3133bd19c739c6b5
! java.lang.ClassCastException: in.cleartax.gst.entities.Rupee cannot be cast to java.math.BigDecimal
! at org.hibernate.type.descriptor.java.BigDecimalTypeDescriptor.areEqual(BigDecimalTypeDescriptor.java:19)
! at org.hibernate.type.AbstractStandardBasicType.isEqual(AbstractStandardBasicType.java:180)
! at org.hibernate.type.AbstractStandardBasicType.isSame(AbstractStandardBasicType.java:170)
! at org.hibernate.type.AbstractStandardBasicType.isDirty(AbstractStandardBasicType.java:206)
! at org.hibernate.type.AbstractStandardBasicType.isDirty(AbstractStandardBasicType.java:202)
! at org.hibernate.type.TypeHelper.findDirty(TypeHelper.java:296)
! at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:4126)
! at org.hibernate.event.internal.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:528)
! at org.hibernate.event.internal.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:215)
! at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:142)
! at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216)
! at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85)
! at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:38)
! at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1295)
! at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:468)
! at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3135)
! at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2352)
! at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
! at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
! at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
! at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
! at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
! at io.dropwizard.hibernate.UnitOfWorkAspect.commitTransaction(UnitOfWorkAspect.java:124)
! at io.dropwizard.hibernate.UnitOfWorkAspect.afterEnd(UnitOfWorkAspect.java:63)
! at io.dropwizard.hibernate.UnitOfWorkApplicationListener$UnitOfWorkEventListener.onEvent(UnitOfWorkApplicationListener.java:79)
! at org.glassfish.jersey.server.internal.monitoring.CompositeRequestEventListener.onEvent(CompositeRequestEventListener.java:71)
! at org.glassfish.jersey.server.internal.process.RequestProcessingContext.triggerEvent(RequestProcessingContext.java:226)
! at org.glassfish.jersey.server.ContainerFilteringStage$ResponseFilterStage.apply(ContainerFilteringStage.java:188)
! at org.glassfish.jersey.server.ContainerFilteringStage$ResponseFilterStage.apply(ContainerFilteringStage.java:163)
! at org.glassfish.jersey.process.internal.Stages.process(Stages.java:171)
! at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:442)
! at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:434)
! at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:329)
! at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
! at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
! at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
! at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
! at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
! at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
! at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
! at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
! at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473)
! at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
! at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388)
! at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341)
! at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228)
! at io.dropwizard.jetty.NonblockingServletHolder.handle(NonblockingServletHolder.java:49)
! at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1689)
! at io.dropwizard.servlets.ThreadNameFilter.doFilter(ThreadNameFilter.java:34)
! at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
! at io.dropwizard.jersey.filter.AllowedMethodsFilter.handle(AllowedMethodsFilter.java:50)
! at io.dropwizard.jersey.filter.AllowedMethodsFilter.doFilter(AllowedMethodsFilter.java:44)
! at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
! at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
! at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1174)
! at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
! at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1106)
! at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
! at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
! at com.codahale.metrics.jetty9.InstrumentedHandler.handle(InstrumentedHandler.java:240)
! at io.dropwizard.jetty.RoutingHandler.handle(RoutingHandler.java:51)
! at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:459)
! at io.dropwizard.jetty.BiDiGzipHandler.handle(BiDiGzipHandler.java:68)
! at org.eclipse.jetty.server.handler.RequestLogHandler.handle(RequestLogHandler.java:56)
! at org.eclipse.jetty.server.handler.StatisticsHandler.handle(StatisticsHandler.java:169)
! at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
! at org.eclipse.jetty.server.Server.handle(Server.java:524)
! at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
! at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
! at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
! at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
! at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
! at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
! at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
! at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
! at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
! at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
! at java.lang.Thread.run(Thread.java:745)
答案 0 :(得分:0)
我一直在创建自己的JavaTypeDescriptor而不是使用BigDecimalTypeDescriptor来解决这个问题。它看起来像这样。
public static class RupeeTypeJavaDescriptor extends AbstractTypeDescriptor<Rupee> {
public RupeeTypeJavaDescriptor() {
super(Rupee.class);
}
@Override
public String toString(Rupee rupee) {
return null;
}
@Override
public Rupee fromString(String s) {
return null;
}
@Override
public <X> X unwrap(Rupee rupee, Class<X> aClass, WrapperOptions wrapperOptions) {
return null;
}
@Override
public <X> Rupee wrap(X x, WrapperOptions wrapperOptions) {
return null;
}
}