Hibernate session.get requires fully qualified class name, despite explicit entity name

I’m using Hibernate 6, and I have some code I’ve been porting that uses Session.get with an entity name and identifier. We do a lot of reflection, and there’s some other background, so this may look a bit odd and explicitly passing the entity name may seem superfluous, but it’s necessary for us.

The entity name by itself doesn’t work, it seems to require the fully qualified name:

@Entity(name = "Root")
...
session.get("Root", rootId); // doesn't work
...
session.persist("Root", root); //works...???

For the session.get, I end up with a

org.hibernate.UnknownEntityTypeException: Unable to locate persister: Root

However,

session.get("mypackage.fully.qual.Root", rootId); // works

How do you map that entity? hbm.xml? Share the mapping please.

It’s an annotated POJO. That’s the entity annotation at the top of the code block, with the explicit name. It used to be hbm.xml mappings, and in that older version of Hibernate, we didn’t have issues with passing the entity name to get like this.

I need to see the entity mappings to be able to help you.

Gotcha…thought it was just that POJO annotation you were looking for.

The mappings are like this (some brevity so hopefully this is all the relevant parts)

package mypackage.fully.qual;

@Entity(name = "Root")
@Table(name = "ROOT")
public class Root extends EntityBase implements java.io.Serializable {
    private static final long serialVersionUID = 1743656930;
    
    private String rootName;
    private List<UniqueCaseRecord> uniqueCaseRecords;

    @NaturalId
    @Column(name = "ROOT_NAME")
    public String getRootName() {
        return this.rootName;
    }

    public void setRootName(String rootName) {
        this.rootName = rootName;
    }
    
    @OneToMany(cascade = jakarta.persistence.CascadeType.ALL, mappedBy = "root")
    public List<UniqueCaseRecord> getUniqueCaseRecords() {
        return this.uniqueCaseRecords;
    }

    public void setUniqueCaseRecords(List<UniqueCaseRecord> uniqueCaseRecords) {
        this.uniqueCaseRecords = uniqueCaseRecords;
    }
}

Then we use this mapped superclass for a bunch of shared configuration and utility.

package mypackage.fully.qual;

@MappedSuperclass
public abstract class EntityBase {
    String guid;
    
    @Column(name = "GUID", nullable = false, length = 16)
    @Id
    @GeneratedValue(generator = "custom-uuid")
    @GenericGenerator(name = "custom-uuid", strategy = "mypackage.fully.qual.UUIDHexGenerator")
    @Type(com.ciminc.hibernate.type.GuidType.class)
    public String getGuid() {
        return this.guid;
    }

    public void setGuid(String guid) {
        this.guid = guid;
    }

    Integer version;
    @Version
    public Integer getVersion(){
        return this.version;
    }

    public void setVersion(Integer version){
        this.version = version;
    }
}

Which Hibernate version are you using? We actually have tests for these cases that ensure the collection is not initialized if the “owning side” is the many-to-one association.

We’re using Hibernate Core 6.1.6.

Update to 6.2.4.Final then please.

I finally am getting back to this, and considered creating a new post, but I figure if anyone else needs this solved, this will show up.

I’ve created a simple webapp for testing this issue using Vaadin 24.4, Spring Boot 3.2.7, and Hibernate ORM 6.4.9.

I have a simple Entity

@Entity(name = "BasicEntity")
@Table(name = "basic_entity")
public class BasicEntity {

    public BasicEntity() {
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    private UUID id;

    public UUID getId() {
        return id;
    }

    public void setId(UUID id) {
        this.id = id;
    }
}

And a simple service

@Service
public class TestService {

    private static final Logger log = LoggerFactory.getLogger(TestService.class);
    @PersistenceContext
    private EntityManager entityManager;

    @Transactional
    public void transact() {
        BasicEntity basicEntity = new BasicEntity();

        Session session = entityManager.unwrap(Session.class);
        UUID id = (UUID) session.save("BasicEntity", basicEntity);
        log.info("Saved BasicEntity: {}", id);
        session.flush();
        session.refresh(basicEntity);
        basicEntity = (BasicEntity) session.get("BasicEntity", basicEntity.getId());
        session.flush();
    }

    @Transactional
    public void transact2() {
        BasicEntity basicEntity = new BasicEntity();

        Session session = entityManager.unwrap(Session.class);
        session.persist("BasicEntity", basicEntity);
        session.flush();
        session.refresh(basicEntity);
        basicEntity = (BasicEntity) session.getReference("BasicEntity", basicEntity.getId());
        session.flush();
    }
}

Both session.getReference and session.get throw the same

java.lang.IllegalArgumentException: Unable to locate persister: BasicEntity

Now if I change get/getReference to use the FQN: it works!

basicEntity = (BasicEntity) session.get("com.example.application.domain.BasicEntity", basicEntity.getId());

Same if I change the get/getReference to be BasicEntity.class, which I imagine is the far more common usage.

Configuration is pretty minimal, I use @EntityScan for BasicEntity’s package, and my application.yml is

spring:
  datasource:
    driverClassName: org.h2.Driver
    url: jdbc:h2:${java.io.tmpdir}/test.db
    username: sa
    password:
  jpa:
    properties:
      hibernate.hbm2ddl.auto: update

Now if I change get/getReference to use the FQN: it works!

You are using a Hibernate API which requires that you pass the “Hibernate Entity-Name”. That is usually the FQN. Use the Class variant instead to avoid this and also the cast.

Entity discovery works for everyone else, so your configuration must be wrong somehow. Try adding the entity classes to a fresh Spring Boot project and you will see it just working.
Whatever isn’t working, this is not the place to ask questions about Spring stuff, but only about Hibernate ORM. Please use the Spring forums for questions about scanning.