您何时在Objectify中注册GAE课程?

所以这可能是一个愚蠢的问题,但你什么时候注册课程:

ObjectifyService.register( User.class ); 

目前,我在类似接口的类的构造函数中这样做,我在其他类中使用它来简化数据存储的使用,特别是我的应用程序。 但是,我收到此错误:

尝试两次注册“用户”

所以,我想我的问题是你在Objectify中注册课程的频率和具体时间是多少?

谢谢!

PS这是我的全class:

 import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Iterator; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.persistence.Id; import com.googlecode.objectify.Objectify; import com.googlecode.objectify.ObjectifyService; import com.googlecode.objectify.annotation.Indexed; import com.googlecode.objectify.annotation.Unindexed; public class UsersService { Objectify ojy; public UsersService(){ ObjectifyService.register( User.class ); ojy = ObjectifyService.begin(); } public void regUser(String email, String password, String firstName, String lastName){ //TODO: Check syntax if email //TODO: store encrypted password } public void regUser(String email, String password, String firstName){ regUser(email, password, firstName, null); } public void regUser(String email, String password){ regUser(email, password, "", ""); } public boolean checkFor(Long acc_id){ User checked_user = ojy.find(User.class, acc_id); if(checked_user == null){ return false; }else{ return true; } } public User getUser(String email, String password) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException{ String pass_enc = MyUtils.getEncrypted(password); Iterable users = ojy.query(User.class).filter("email", email).filter("password", pass_enc); Iterator iter = users.iterator(); if(iter.hasNext()){ return iter.next(); }else{ return null; } } } 

更新

这是最佳实践解决方案:

使用您自己的服务,这可以保证您的实体在使用Objectify之前已注册,但不一定会影响应用程序启动以查看不访问数据存储区的请求。

 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(); } } 

然后像这样使用它:

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

原始答案(更好地使用上面的代码):

你应该在你的class级这样做,只需要像这样放一个静态块:

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

ps,你也看看物化的最佳实践

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

我使用@Entity注释, Reflections库和运行时注册,对我的任何应用程序的启动时间没有重大影响,因为所有信息都是在编译/构建时收集的。

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> 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 */ } } 

基于Danie的答案,如果其他人正在使用dependency injection,我为Spring MVC做了这个并且工作得很完美:

我创建了一个服务如下:

 @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(); } } 

然后每当我想使用它时,我只是注入这样的服务:

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

然后我像这样使用它:

 objectifyService.ofy().save().entity(user).now();