2016-06-13 2 views
0

Как я могу управлять действиями по созданию, редактированию и удалению с помощью entites как можно проще?JPA создавать, редактировать и удалять объекты из базы данных

Например:

Пользователь:

public class User { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    private String name; 

    ... 

    // Item can't exist without user 
    @OneToMany(cascade=CascadeType.ALL,mappedBy = "user",orphanRemoval=true) 
    private Set<Item> items = new HashSet<Item>(); 

    public Set<Item> getItems() { return items; } 

    public void addItem(Item item) { 
     items.add(item); 
    } 

    public void removeItem(Item item) { 
     if(!items.contains(item)) return; 
     items.remove(item); 
    } 

    // Group can exist without a user 
    @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH},mappedBy="users") 
    private Set<Group> groups = new HashSet<Group>(); 

    public Set<Group> getGroups() { return groups; } 

    public void setGroups(Set<Group> groups) { this.groups = groups; } 

    public void addGroup(Group group) { 
     groups.add(group); 
    } 

    publi void removeGroup(Group group) { 
     if(!groups.contains(group)) return; 
     groups.remove(group); 
    } 

    ... 
} 

Группа:

@Entity 
public class Group { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    private String name; 

    ... 

    @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}) 
    @JoinTable(name = "GroupToUser", joinColumns = 
    @JoinColumn(name = "GroupId", referencedColumnName="Id"), inverseJoinColumns = 
    @JoinColumn(name = "UserId", referencedColumnName="Id")) 
    private Set<User> users = new HashSet<User>(); 

    public Set<User> getUsers() { return users; } 

    public void setUsers(Set<User> users) { this.users = users; } 

    public void addUser(User user) { 
     user.addGroup(this); 
    } 

    publi void removeUser(User user) { 
     if(!users.contains(user)) return; 
     users.remove(user); 
    } 

    ... 
} 

товара:

@Entity 
public class Item { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    private String name; 

    ... 

    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}) 
    @JoinColumn(name="UserId") 
    private User user; 

    public Set<User> getUser() { return user; } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    publi void removeUser() { 
     this.user = null; 
    } 

    ... 
} 

Могу ли я с помощью JPA аннотации правильно?

Что мне написать здесь?

EntityManager em = getEntityManager(); 
em.getTransaction().begin(); 
??? 
em.getTransaction().commit(); 

ли я просто позвонить em.remove/сохраняться/слияния методы удаления/создания/редактирования операции?

И когда я должен использовать метод javax.persistence.EntityManager.getReference в этих операциях?

+0

Вы, кажется, понимаете, что экземпляр EntityManager используется для управления объектами JPA. Вы пробовали проверить его? – scottb

ответ

0

Find() отправляет объект из кеша контекста персистентности или если его там нет, он будет загружен из базы данных.

GetReference() не загружает объект немедленно. Возвращается прокси (определенный объект, так называемый «заместитель» с обогащенными методами для загрузки фактического объекта). Так что это реализация с помощью LazyLoading.

Только если атрибуты прокси-сервера или других методов сохранения необходимы/называются прокси-сервером, он взаимодействует и загружает фактический объект из базы данных.

Например:

User us = em.find(User.class, 70992); 

GetReference() используется аналогично.

User us = em.getReference(User.class, 70922); 

Если объект для идентификатора пользователя не известно, в контексте сохранения состояния, EntityNotFoundException() выбрасывается.

Обычно я использую метод getReference, когда мне не нужно обращаться к состоянию базы данных (я имею в виду метод getter). Просто изменить состояние (я имею в виду метод setter).

В вышеописанном случае, если я хочу, чтобы обновить возраст пользователя, как показано ниже, после получения пользователя:

setAge(age); 

Если я вызываю метод найти, поставщик JPA, за кулисами, буду называть

SELECT NAME, AGE FROM USER WHERE USER_ID = ? 

UPDATE USER SET AGE = ? WHERE USER_ID = ? 

Если я вызову метод getReference, поставщик JPA, за кулисами, позвонит

UPDATE PERSON SET AGE = ? WHERE USER_ID = ? 

Потому что когда вы вызываете getReference, вы получите прокси-объект.

Для отдыха мы должны использовать удалить, сохраняются и слияния, как вы сказали

0

Лично я рекомендую прочитать о Repository Software Pattern и Single Responsability Principle.

Моей идеей было бы создать, например, UserRepository, а другой класс, например контроллер, перейдет в этот репозиторий после создания необходимых объектов и попытается их сохранить.

Должно работать так:

Сначала получите менеджер сущности и сделки, как ты, а затем попытаться persist() сущностей. Если метод persist() обнаруживает, что объект находится в постоянстве, он выдает PersistenceException. Поймайте его, получите новую транзакцию и вызовите метод merge().

+0

Если вы не знаете, является ли это новым, почему бы просто не использовать слияние и позволить JPA обрабатывать вставку или обновление? – Chris

0

Самый простой способ - не лучший способ. Самый лучший простой способ это один, я думаю (но относительно действий обновления, вы лучше прочитать больше о JPQL namedQueries/orm.xml):

@WebFilter("*.htm") 
public class JPAFilter implements Filter { 
    private static final EntityManagerFactory entityManagerFactory 
     = Persistence.createEntityManagerFactory(/* yourprojectname */); 
    private static final ThreadLocal<EntityManager> entityManagers 
     = new ThreadLocal<>(); 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException {} 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, 
     FilterChain chain) throws IOException, ServletException { 
      entityManagers.set(entityManagerFactory.createEntityManager()); 
     EntityManager entityManager = entityManagers.get(); 
     try { 
      request.setCharacterEncoding("UTF-8"); 
      chain.doFilter(request, response); 
     } finally { 
      if (entityManager.getTransaction().isActive()) { 
       entityManager.getTransaction().rollback(); 
      } 
      entityManager.close(); 
      entityManagers.remove(); 
     } 
    } 

    public static EntityManager getEntityManager() { 
     return entityManagers.get(); 
    } 

    @Override 
    public void destroy() { 
     entityManagerFactory.close(); 
    } 
} 

---- 

abstract class AbstractDAO { 
    protected EntityManager getEntityManager() { 
     return JPAFilter.getEntityManager() 
    } 
} 

---- 

public class UserDAO extends AbstractDAO { 
    public void create(User user) { 
     getEntityManager().persist(user); 
    } 

    public User read(long id) { 
     return getEntityManager().find(User.class, id); 
    } 

    public void delete(long id) { 
     if (user != null) { 
      getEntityManager().remove(user); 
     } 
    } 
} 

---- 

abstract class AbstractService { 
    private EntityManager getEntityManager() { 
     return JPAFilter.getEntityManager(); 
    } 

    protected void beginTransaction() { 
     getEntityManager().getTransaction().begin(); 
    } 

    protected void commit() { 
     getEntityManager().getTransaction().commit(); 
    } 

    protected void rollback() { 
     getEntityManager().getTransaction().rollback(); 
    } 
} 

---- 

public class UserService extends AbstractService { 
    private final UserDAO userDAO = new UserDAO(); 

    public void create(User user) { 
     beginTransaction(); 
     userDAO.create(user); 
     commit(); 
    } 

    public User read(long id) { 
     return userDAO.read(id) 
    } 

    public void delete(long id) { 
     userDAO.delete(id); 
    } 
} 

---- 

@WebServlet("/users.htm") 
public class ManageUsersServlet extends HttpServlet { 
    private static final long serialVersionUID = 1L; 
    private static final String VIEW = "/WEB-INF/JSP/users.jsp"; 
    private final transient UserService userService = new UserService(); 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
     // here you do whatever you want using your userService methods. 
    } 
} 

P.S. Не забывайте блокировать записи из базы данных при обновлении (используя пессимистическую блокировку или исключение оптимистичной блокировки).

Вы также можете найти лоты об этом, если вы ищете «CRUD Operations with JPA». Первый учебник, который я нашел, следующий: http://www.objectdb.com/java/jpa/persistence/crud

0

Я использую аннотации jpa справа?

На первом взгляде, я бы только вопрос об отсутствии поля @version, которое необходимо для EntityManager выполнять оптимистическую блокировку, которая является стандартной защитой от потерянных обновлений, если вы не используете сериализуемый уровень изоляции (что потребует специальной настройки для многих систем баз данных).

Должен ли я просто вызвать методы em.remove/persist/merge для операций удаления/создания/редактирования?

Это самый простой и обычно лучший способ.

И когда я должен использовать метод javax.persistence.EntityManager.getReference в этих операциях?

getReference полезен, если вы хотите обратиться к объекту без загрузки его данных из базы данных. Например, вы могли бы:

public void updateUser(Item item, int userId) { 
    item.setUser(entityManager.getReference(User.class, userId)); // does not require a query 
    entityManager.merge(item); 
} 

Сделки

Вы хотите откатить транзакцию, если исключение и закройте EntityManager, как только вы сделали с ним (как в случае успеха и неудачи).

Относительно примечания, если ваше приложение не является крошечным, вы захотите изучить декларативное управление транзакциями, чтобы вам не приходилось их кодировать для каждой операции.Например, весной вы просто комментируете класс с @Transactional, чтобы Spring начинал (и заканчивал) транзакцию всякий раз, когда вызывается метод.

Смежные вопросы