我应该如何尽可能简单地管理创建,编辑和删除操作?
例如:
用户:
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 / persist / merge方法?
我应该何时在这些操作中使用javax.persistence.EntityManager.getReference方法?
答案 0 :(得分:1)
Find()从持久化上下文的缓存中提供实体,或者如果不在那里,它将从数据库加载。
GetReference()不会立即加载实体。返回一个代理(某个对象,一个所谓的“代理”,带有用于加载实际实体的丰富方法)。所以它是在LazyLoading的帮助下实现的。
只有在需要/调用代理或其他持久性方法的属性时,代理才会从数据库中交互并加载实际实体。
例如:
User us = em.find(User.class, 70992);
类似地使用GetReference()。
User us = em.getReference(User.class, 70922);
如果持久化上下文中未知用户标识的实体,则抛出EntityNotFoundException()。
当我不需要访问数据库状态时,我通常使用getReference方法(我的意思是getter方法)。只是改变状态(我的意思是设定方法)。
在上述情况下,如果我想在获得用户后更新用户的年龄:
setAge(age);
如果我调用find方法,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时,你会得到一个代理对象。
为了休息,我们必须像你说的那样使用删除,保持和合并
答案 1 :(得分:0)
我个人建议您阅读Repository Software Pattern和Single Responsability Principle。
我的想法是创建一个UserRepository,另一个类,比如Controller,在创建必要的对象并尝试持久化之后会转到该存储库。
应该像这样工作:
首先获取实体管理器和事务,然后尝试persist()
实体。如果persist()
方法检测到实体处于持久性状态,则会抛出PersistenceException
。抓住它,获取新的交易并调用merge()
方法。
答案 2 :(得分: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。更新时不要忘记从数据库锁定记录(使用悲观锁或捕获乐观锁异常)。
如果您使用JPA&#34;搜索&#34; CRUD操作,您也可以找到很多相关信息。我找到的第一个教程就是这个:http://www.objectdb.com/java/jpa/persistence/crud
答案 3 :(得分: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(在成功和失败的情况下)。
在相关的说明中,如果您的应用程序不是很小,您将要查看声明式事务管理,这样您就不必为每个操作编写代码。例如,在Spring中,您只需使用@Transactional对类进行注释,以便在调用方法时让Spring启动(并结束)事务。