When do you register classes in Objectify for GAE?

后端 未结 3 1381
无人共我
无人共我 2021-02-05 12:08

So this might be kind of a dumb question but when do you register classes with:

ObjectifyService.register( User.class );

Currently, I\'m doing

相关标签:
3条回答
  • 2021-02-05 12:18

    I use the @Entity annotation, the Reflections library and runtime registration with no significant impact in start up time of any of my applications because all the information is collected at compile/build time.

    ObjectifyLoaderContextListener.java

    package com.vertigrated.servlet;
     
    import com.google.appengine.api.ThreadManager;
    import com.googlecode.objectify.ObjectifyFactory;
    import com.googlecode.objectify.ObjectifyService;
    import com.googlecode.objectify.annotation.Entity;
    import org.reflections.Reflections;
    import org.reflections.util.ClasspathHelper;
    import org.reflections.util.ConfigurationBuilder;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
     
    import javax.annotation.Nonnull;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import java.util.HashSet;
    import java.util.Set;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
     
    /**
     * This class processes the classpath for classes with the @Entity or @Subclass annotations from Objectify
     * and registers them with the ObjectifyFactory, it is multi-threaded uses a prebuilt list of classes to process
     * created by the Reflections library at compile time and works very fast!
     */
    public class ObjectifyLoaderContextListener implements ServletContextListener
    {
        private static final Logger L = LoggerFactory.getLogger(ObjectifyLoaderContextListener.class);
     
        private final Set<Class<?>> entities;
     
        public ObjectifyLoaderContextListener()
        {
            this.entities = new HashSet<>();
        }
     
        @Override
        public void contextInitialized(@Nonnull final ServletContextEvent sce)
        {
            final ConfigurationBuilder cb = new ConfigurationBuilder();
            cb.setUrls(ClasspathHelper.forPackage(""));
            final ExecutorService es = Executors.newCachedThreadPool(ThreadManager.currentRequestThreadFactory());
            cb.setExecutorService(es);
            final Reflections r = new Reflections(cb);
            this.entities.addAll(r.getTypesAnnotatedWith(Entity.class));
            es.shutdown();
            final ObjectifyFactory of = ObjectifyService.factory();
            for (final Class<?> cls : this.entities)
            {
                of.register(cls);
                L.debug("Registered {} with Objectify", cls.getName());
            }
        }
     
        @Override
        public void contextDestroyed(@Nonnull final ServletContextEvent sce)
        {
            /* this is intentionally empty */
        }
    }
    
    0 讨论(0)
  • 2021-02-05 12:22

    Based on Danie's answer and in case someone else is using dependency injection I did this for Spring MVC and worked perfect:

    I created a service as follows:

    @Service
    @Qualifier("objectifyService")
    public class OfyService {
        static {
            ObjectifyService.register(GaeUser.class);
        }
    
        public static Objectify ofy() {
            return ObjectifyService.ofy();
        }
    
        public static ObjectifyFactory factory() {
            return ObjectifyService.factory();
        }
    
    }
    

    Then whenever I want to use it I just inject the service like this:

    @Autowired
    @Qualifier("objectifyService")
    OfyService objectifyService;
    

    And then I use it like this:

    objectifyService.ofy().save().entity(user).now();
    
    0 讨论(0)
  • 2021-02-05 12:33

    Update

    Here is the Best Practice Solution:

    Use Your Own Service , This guarantees that your entities are registered before you use Objectify, but doesn't necessarily impact application startup for requests which do not access the datastore.

    import com.googlecode.objectify.Objectify;
    import com.googlecode.objectify.ObjectifyFactory;
    import com.googlecode.objectify.ObjectifyService;
    
    
    public class OfyService {
        static {
            ObjectifyService.register(User.class);
        }
    
        public static Objectify ofy() {
            return ObjectifyService.begin();//prior to v.4.0 use .begin() , 
                                            //since v.4.0  use ObjectifyService.ofy();
        }
    
        public static ObjectifyFactory factory() {
            return ObjectifyService.factory();
        }
    
    }
    

    Then use it like this:

    public User createUser(User pUser) {
    
        Objectify objectify = OfyService.ofy();
        objectify.put(pUser);
    
        return pUser;
    }
    

    Original Answer (better use the code above):

    you should do it this way in your class, just put a static block like this:

    static{
        ObjectifyService.register( User.class );
    }
    

    p.s , you take a look at the best practice of objectify too

    http://code.google.com/p/objectify-appengine/wiki/BestPractices

    0 讨论(0)
提交回复
热议问题