1

I'm currently debugging the code that calls the Hibernate Entity manager to load the data from the Postgres DB. I do calls for two different ids in DB that corresponds to the almost the same DB entries (no null values, all fields are in accordance with @Entity fields and follow the same format) and get so different object details in debugger window.

The fist one is ServiceEntity@32589 that corresponds to the id=594:

enter image description here

Please note that provider and category fields here has _$$_jst3f5_ prefix, like it isn't exactly the same class as just CategoryEntity and PaymentEntity

While when calling for another id=595, I'm getting not ServiceEntity, but ServiceEntity_$$_jst3f5_3e@32572 with all the same fields being null.

enter image description here

What could be the reason? This happens only on specific calls of this method by the overlying method, not at all.

So, the method I called in debugger was:

   @Override
        public ServiceEntity getServiceById(int serviceId) {
            List<ServiceEntity> list = em.createQuery("select s from ServiceEntity s where s.id = :id", ServiceEntity.class)
                    .setParameter("id", serviceId)
                    .getResultList();
    
            return (list.isEmpty() ? null : list.get(0));
        }

and it is called from the

 @Transactional(readOnly = true)
    public ProviderService getProviderService(int serviceId) {
        if (serviceProviderCache.get(serviceId) != null) {
            return serviceProviderCache.get(serviceId);
        }

        ServiceEntity serviceEntity = pServiceDao.getServiceById(serviceId);
        if (settingService.isEnableGateway() && (Arrays.stream(GatewayProviderImpl.GATEWAY_PROVIDERS)
                .anyMatch(p -> serviceEntity.getProviderId().equals(p)))) {
            serviceProviderCache.put(serviceId, providersCache.get(GatewayProviderImpl.PROVIDER_ID));
        } else {
            serviceProviderCache.put(serviceId, providersCache.get(serviceEntity.getProvider().getId()));
        }

        return serviceProviderCache.get(serviceId);
    }

where I do have the problem I have described. And it is also called from another @Transactional method too (non readonly).

and here (not @Transactional)

  @Override
    public void enter(ViewChangeListener.ViewChangeEvent event) {
        int serviceId = Integer.parseInt(event.getParameters());
        service = pServiceService.getServiceById(serviceId);
  

I have not problem with that. Note, that in first method, the called id=595 is the same as id that was passed as the parameter to the @Transaction marked method, while id=594 isn't equal to that object. So how @Transactional can make this to happen, and only for specific data from the DB?

What _$$_jst3f5_ stands for?

ServiceEntity:



@Entity
@Table(name = "services")
public class ServiceEntity {
    @Id
    @SequenceGenerator(name="service_gen", sequenceName="services_id_seq", allocationSize = 1)
    @GeneratedValue(generator="service_gen")
    private Integer id;
    @Column(nullable = false, length = 100)
    private String name;
    @Column(name = "account_caption")
    private String accountCaption;
    private String code;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "category_id")
    private CategoryEntity category;
    @Column(name = "category_id", insertable = false, updatable = false)
    private Integer categoryId;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "provider_id")
    private ProviderEntity provider;
    @Column(name = "provider_id", insertable = false, updatable = false)
    private String providerId;
    @Column(name = "image_path")
    private String imagePath;
    @Column(name = "is_blocked")
    private boolean blocked;
    private String mask;
    @Column(name = "terminal_mask")
    private String terminalMask;
    private boolean base;
    @Column(name = "only_identified")
    private boolean onlyIdentified;
    @Column(name = "additional_fields")
    private boolean additionalFields;
    @Column(name = "destination_view_format")
    private String destinationViewFormat;
    @Column(name = "is_fixed_amount")
    private boolean fixedAmount;
    @Column(name = "is_user_amount")
    private boolean userAmount;
    @Column(name = "is_terminal_change")
    private boolean terminalChange;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "currency_id")
    private CurrencyEntity currency;
    @Column(name = "currency_id", insertable = false, updatable = false)
    private String currencyId;
    @Column(name = "display_order")
    private Integer displayOrder;
    @Column(name = "keep_validation_result")
    private boolean keepValidationResult;
    @Column(name = "is_multi_currency")
    private boolean multiCurrency;
    @OneToMany(mappedBy = "service")
    private Collection<AgentServiceAccessEntity> serviceAccesses;
    @OneToMany(mappedBy = "service")
    private Collection<HotServiceEntity> hotServices;
    @OneToMany(mappedBy = "service")
    private Collection<ServicePrefixEntity> servicePrefixes;
    @OneToMany(mappedBy = "service")
    private Collection<ServiceFieldEntity> serviceFields;
    @OneToMany(mappedBy = "service")
    private Collection<ServiceInfoBlockEntity> infoBlocks;
    @OneToMany(mappedBy = "service")
    private Collection<ServiceLimitEntity> limits;
    @OneToMany(mappedBy = "service")
    private Collection<RegistryColumnEntity> registryColumns;

The queries, that were actually sent, are:

select serviceent0_.id as id1_97_, serviceent0_.account_caption as account_2_97_, serviceent0_.additional_fields as addition3_97_, serviceent0_.base as base4_97_, serviceent0_.is_blocked as is_block5_97_, serviceent0_.category_id as category6_97_, serviceent0_.code as code7_97_, serviceent0_.currency_id as currency8_97_, serviceent0_.destination_view_format as destinat9_97_, serviceent0_.display_order as display10_97_, serviceent0_.is_fixed_amount as is_fixe11_97_, serviceent0_.image_path as image_p12_97_, serviceent0_.keep_validation_result as keep_va13_97_, serviceent0_.mask as mask14_97_, serviceent0_.is_multi_currency as is_mult15_97_, serviceent0_.name as name16_97_, serviceent0_.only_identified as only_id17_97_, serviceent0_.provider_id as provide18_97_, serviceent0_.is_terminal_change as is_term19_97_, serviceent0_.terminal_mask as termina20_97_, serviceent0_.is_user_amount as is_user21_97_ from services serviceent0_ where serviceent0_.id=?

for that was called from the app code without debug call, the same is called from Evaluate window of debug mode, while addding to serviceId specific values like 594 and 595.

So, looks like Hibernate extracts the same values from the DB, but then looses the retrieved data.

UPD. It turns out, that they are called consequentially, both initiated by the Vaadin UI actions.

1)

public void enter(ViewChangeListener.ViewChangeEvent event) {
            int serviceId = Integer.parseInt(event.getParameters());
            service = pServiceService.**getServiceById**(serviceId);
  
  1. @Transactional(readOnly = true) public ProviderService getProviderService(int serviceId) { if (serviceProviderCache.get(serviceId) != null) { return serviceProviderCache.get(serviceId); }

          ServiceEntity serviceEntity = pServiceDao.**getServiceById**(serviceId);
          if (settingService.isEnableGateway() && (Arrays.stream(GatewayProviderImpl.GATEWAY_PROVIDERS)
                  .anyMatch(p -> serviceEntity.getProviderId().equals(p)))) {
              serviceProviderCache.put(serviceId, providersCache.get(GatewayProviderImpl.PROVIDER_ID));
          } else {
              serviceProviderCache.put(serviceId, providersCache.get(serviceEntity.getProvider().getId()));
          }
    
          return serviceProviderCache.get(serviceId);
      }
    

And if in the first method serviceId would be =594, the first execution is ok, it returns some data, while on the second execution of getServiceById(serviceId) the null-fields data is returned.

If I would take the Evaluate tool and explicitly call for

**getServiceById**(595)

at the debug step 2), I would get the non-null data. If now I would do

**getServiceById**(594), I'm also getting the null-filled data

Like execution of point 1) forces entity manager to return something wrong and if it isn't executed for the specific id, it works properly

WHat is the root cause of that and how to work it around?

Eljah
  • 4,188
  • 4
  • 41
  • 85

0 Answers0