У меня есть AngularJS переднего конца, который делает несколько запросов к различным ресурсам на Java фонового работает Wildfly 10.JPA запрос не находя объект после того, как сохраняется
Каждый конечной ресурс запрашивает базу данных (MySQL 5.6), чтобы найти пользователь использует уникальный идентификатор пользователя из токена доступа (это не первичный ключ, он имеет уникальный индекс).
В случае, если пользователь не найден в базе данных, я создаю его из маркеров информации доступа, см ниже:
public abstract class AbstractService {
@PersistenceContext
protected EntityManager em;
...
}
public abstract class AbstractResource extends AbstractService {
@EJB
UserService userService;
@EJB
UserRegistrationService userRegistrationService;
public User getUser(AccessToken token) {
User user = userService.findByKcId(token.getUserId());
if (user == null) {
user = userRegistrationService.findOrCreateUser(token);
}
return user;
}
...
}
Я создал синглтон, чтобы убедиться, что пользователь только создается, если это действительно Безразлично Уже существует.
@Singleton
@Startup
public class UserRegistrationService {
@PersistenceContext
EntityManager em;
@EJB
UserService userService;
public User findOrCreateUser(AccessToken token) {
String kcId = token.getUserId();
User user = this.findByKcId(kcId);
if (user == null) {
user = new User();
user.setKcId(kcId);
...
em.persist(user);
em.flush();
em.refresh(user);
}
return user;
}
private User findByKcId(String kcId) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> criteria = cb.createQuery(User.class);
Root<User> user = criteria.from(User.class);
criteria.select(user).where(cb.equal(user.get(User_.kcId), kcId));
List<User> users = em.createQuery(criteria)
.setMaxResults(1)
.getResultList();
if (users.isEmpty()) {
return null;
}
return users.get(0);
}
...
}
Но по какой-то причине первого раза знаки в системе пользователя, все запросы (наша домашняя страница делает 3 запроса асинхронных) запускает INSERT в базе данных, что приводит к:
MySQLIntegrityConstraintViolationException: Duplicate entry ...
Несмотря на то, первый запрос уже создал нового пользователя в базе данных. После первого входа все работает нормально.
Любые идеи?
UPDATE:
Я создал метод внутри UserRegistrationService для поиска пользователей и один и тот же EM с помощью метода findOrCreateUser.
Также здесь есть EntityManager хэш-код() Выход:
11:53:32,344 INFO [stdout] (default task-21) UserService.findKcById: 11694883
11:53:32,416 INFO [stdout] (default task-21) UserRegistrationService.findOrCreateUser: 212546987
11:53:32,416 INFO [stdout] (default task-21) UserRegistrationService.findKcById: 212546987
11:53:32,423 INFO [stdout] (default task-20) UserService.findKcById: 11694883
11:53:32,495 INFO [stdout] (default task-20) UserRegistrationService.findOrCreateUser: 212546987
11:53:32,495 INFO [stdout] (default task-20) UserRegistrationService.findKcById: 212546987
11:53:32,553 INFO [stdout] (default task-26) UserService.findKcById: 11694883
UPDATE 2: LOG
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '8f262ed0-3868-449e-aea8-b2af55209479' for key 'kc_id2_UNIQUE'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
at com.mysql.jdbc.Util.getInstance(Util.java:387)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:934)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3870)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3806)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2470)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2617)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2550)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009)
at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5094)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994)
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:537)
Спасибо!
Как вы получаете ссылки EntityManager? Я предполагаю, что у вас есть 2 разных ЭМ (и, следовательно, 2 разных транзакции). –
@SteveEbersole только что отредактировал мой код. Я ввел EntityManager в абстрактный класс. Кроме того, они представляют собой 3 разных запроса, не являются ли они уже 3 различными транзакциями по одному для каждого запроса? – Bruno
Я действительно не понимаю, почему «AbstractService» имеет свои классы расширения в качестве членов. Это я, как недостаток дизайна (или, скорее, недостаток), для меня. – Antoniossss