Когда вы регистрируете классы в Objectify for GAE?
Таким образом, это может быть своего рода глупым вопросом, но когда вы регистрируете классы с помощью:
ObjectifyService.register( User.class );
В настоящее время я делаю это в конструкторе класса, подобного интерфейсу, который я использую в своих других классах, чтобы упростить использование хранилища данных специально для моего приложения. Однако я получаю эту ошибку:
Попытка зарегистрировать вид "Пользователь" дважды
Итак, я думаю, мой вопрос в том, как часто и конкретно, когда вы регистрируете классы в Objectify?
Спасибо!
P.S. Здесь весь мой класс:
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<User> users = ojy.query(User.class).filter("email", email).filter("password", pass_enc);
Iterator<User> iter = users.iterator();
if(iter.hasNext()){
return iter.next();
}else{
return null;
}
}
}
Ответы
Ответ 1
Обновление
Вот лучшее решение для практики:
Используйте свой собственный сервис, Это гарантирует, что ваши объекты зарегистрированы до использования 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;
}
Оригинальный ответ (лучше использовать код выше):
вы должны сделать это таким образом в своем классе, просто поместите статический блок следующим образом:
static{
ObjectifyService.register( User.class );
}
p.s, вы также смотрите на лучшую практику объективирования.
http://code.google.com/p/objectify-appengine/wiki/BestPractices
Ответ 2
Я использую аннотацию @Entity
, библиотеку Reflections и учет времени выполнения без существенного влияния на время запуска любого из моих потому что вся информация собирается в момент компиляции/сборки.
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 */
}
}
Ответ 3
Основываясь на ответе Дани, и если кто-то использует инъекцию зависимостей, я сделал это для 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();