0

I have entity.

@Entity
class Foo {
    @Column
    Long id;
    /* ... */
}

Hibernate generates Metamodel for it:

@StaticMetamodel(Foo.class)
public abstract class Foo_ {
    public static volatile SingularAttribute<Foo, Long> id;
    /* ... */
}

I want to do some tests without database connection. But I need to get value of Foo_.id.getName() for use in reflection.

Unfortunately it doesn't work in test context. This test failed:

@Test
public void metaModelTest() {
    Assert.assertTrue(Foo_.id != null);
}

I found here: JPA/Hibernate Static Metamodel Attributes not Populated -- NullPointerException

When the Hibernate EntityManagerFactory is being built, it will look for a canonical metamodel class for each of the managed typed is knows about and if it finds any it will inject the appropriate metamodel information into them, as outlined in [JPA 2 Specification, section 6.2.2, pg 200]

Is there way to get mock EntityManagerFactory that will do it? Perhaps there are other solutions?

Note: tests are in Spring test context.

Community
  • 1
  • 1
Tarwirdur Turon
  • 751
  • 5
  • 17

1 Answers1

2

My current solition is this:

@Component
@SuppressWarnings({ "rawtypes", "unchecked", "serial" })
public class MockMetaModelGenerator {
    private static final String BASE_PACKAGE = "com.example.foo";

    @PostConstruct
    public void init() {
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(Entity.class));
        for (BeanDefinition bd : scanner.findCandidateComponents(BASE_PACKAGE)) {
            Class<?> metamodel;
            try {
                metamodel = Thread.currentThread().getContextClassLoader().loadClass(bd.getBeanClassName() + "_");
                for (Field field : metamodel.getFields()) {
                    field.set(null, new GenericAttrImpl(field.getName()));
                }
            } catch (Exception e) {
                Throwables.propagate(e);
            }
        }
    }

    static class GenericAttrImpl extends AbstractAttribute implements CollectionAttribute, SetAttribute, ListAttribute, MapAttribute,
            SingularAttribute {
        GenericAttrImpl(String name) {
            super(name, null, null, null, null);
        }
        /* Mock realization of other methods */
    }
}

Full code on pastebin: http://pastebin.com/Ncc8Ty46

Ugly but works.

Tarwirdur Turon
  • 751
  • 5
  • 17