如何在没有不变性的情况下将@TypeDef与Hibernate Transaction一起使用

时间:2017-01-12 09:57:45

标签: hibernate jpa dropwizard

我有一个用例,我在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)

1 个答案:

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