0

我不再喜欢写 em.persist() 了。我可以在返回新实例时执行此操作吗?

嗯,也许 id 与 grails-domains 混淆了。

例如,我有一个 AppConfig.java:

package spring;
import org.springframework.context.annotation.*;
import org.springframework.orm.jpa.*;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.*;

@Configuration
@EnableAspectJAutoProxy
@EnableTransactionManagement
public class AppConfig implements TransactionManagementConfigurer {

    @Bean
    public LocalEntityManagerFactoryBean entityManagerFactory() {
        LocalEntityManagerFactoryBean bean = new LocalEntityManagerFactoryBean();
        bean.setPersistenceUnitName("persistenceUnit");
        return bean;
    }

    @Bean
    @Scope("session")
    public Test test() {
        return new Test();
    }

    @Bean
    public JpaTransactionManager txManager() {
        return new JpaTransactionManager();
    }

    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return txManager();
    }
}

和一个实体用户

package spring;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity @Table(name = "User")
public class User {
    private long id;
    @Id
    @GeneratedValue
    public long getId() { return id; }
    public void setId(long id) { this.id = id; }


    private String name;
    @Column
    public void setName(String name) { this.name = name; }
    public String getName() { return name; }

}

一个persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <persistence-unit name="persistenceUnit">
        <properties>
            <property name="hibernate.ejb.cfgfile" value="/META-INF/hibernate.cfg.xml" />
        </properties>
    </persistence-unit>
</persistence>

和一个hibernate.cfg.xml

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
        <session-factory name="sessionFactory">
            <property name="hibernate.hbm2ddl.auto">false</property>
            <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
            <property name="hibernate.connection.password"></property>
            <property name="hibernate.hbm2ddl.auto">create-drop</property>
            <property name="hibernate.connection.url">jdbc:hsqldb:mem:jamsession</property>
            <property name="hibernate.connection.username">sa</property>
            <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
            <property name="hibernate.search.autoregister_listeners">false</property>
            <property name="hibernate.show_sql">true</property>
            <property name="hibernate.format_sql">false</property>
            <mapping class="spring.User" />
        </session-factory>
    </hibernate-configuration>

一个名为 Test 的控制器:

package spring;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;

@Controller
public class Test {
    @PersistenceContext
    transient EntityManager em;

    @Transactional
    public User newUser(String name) {
        User user = new User();
        user.setName(name);
        // em.persist(user);
        return user;
    }

    public List<User> getUsers() {
        return em.createQuery("from User").getResultList();
    }
}

最后但同样重要的是,这个 index.jsp:

<%@page import="spring.User"%>
<%@page import="spring.Test"%>
<%@page import="org.springframework.web.context.WebApplicationContext"%>
<%@page import="org.springframework.web.context.support.WebApplicationContextUtils"%>
<%
    WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
    Object o = wac.getBean("appConfig");
    Test test = (Test) wac.getBean("test");
    if (request.getParameter("insert") != null) {
        test.newUser(request.getParameter("name"));
    }
%>
<ol>
<% for (User u : test.getUsers()) {
     out.print("<li>"+u.getName()+"</li>");
   } %>
</ol>

<form method="post">
  <input type="text" name="name" value="unnamed" />
  <input type="submit" value="Insert" name="insert" />
</form>

要使用插入按钮保存新用户,我需要 em.persist(user);!我怎样才能摆脱 em.persist?

4

4 回答 4

1

你可以摆脱em.persist使用AOP:)你可以自己做一个注释,在函数被执行后做em.persist()它返回的任何事情:)..

你可以 :

  1. 在java ee的情况下编写一个拦截器......
  2. 如果您使用 spring,请使用aspectj或 AOP
  3. 使用 some DAOs 来操作对象

如果您正在使用 Spring 使用 AOP 会容易得多......只需用谷歌搜索 AOP 并发明你想要的任何东西......

你也可以使用spring-data...给你很多东西...只需编写一个接口就完成了...spring-data将实现您的接口...

在这里你可以看到一个spring-data项目

  1. 弹簧数据 JPA
  2. 将由 spring 实现的接口(使用 AOP)

PS:这不是一个玩笑...您不必为该接口编写任何实现...您只需要使用“ save()findUserByName(String name)”等命名约定...

于 2013-03-04T19:05:44.267 回答
1

您可以做到这一点的一种方法是使用来自根对象的级联。在您的情况下,也许Users 属于 a Department。您可以将该类@OneToMany映射到User,标记为CascadeType.ALL

@Entity
public class Department {
    @OneToMany(mappedBy = "department", cascade = CascadeType.ALL)
    private Set<User> users;
}

然后要创建一个用户,您将创建它并将其添加到Department

Department d = em.find(Department.class, "Coinage");
User u = new User("Felix Schlag");
d.addUser(u);

提交封闭事务时,Department将保存现有但已修改的事务,并且保存的内容也将级联到新事务User

如果没有User像 a 这样的自然聚合Department,您可以为所有用户创建一个主根对象。或者,您可以将用户分类为类型(管理员、客户、作者等),并UserType为每个类型创建一个实例,其中包含该类型的所有用户的集合。

最后我应该说,虽然这种方法在技术上是可行的,但我认为这通常不是一个好主意。我会担心遇到与多个线程同时更新根对象的集合相关的问题(这可能表现为事务提交失败),或者将这些巨大的集合加载到内存中(这不应该是必要的,但无论如何都可能发生) )。

于 2013-03-04T20:06:42.073 回答
1

是的你可以。此外,您还可以:

  • 用更少的代码完成相同的功能
  • 用更简单的代码完成相同的功能
  • 使用更易于阅读的代码完成相同的功能
  • 使用更易于理解的代码完成相同的功能
  • 更有效率
  • 减少耦合(这使您的代码维护成本更低)

您可以通过使用 GORM 而不是 CMP 来获得所有这些。请注意,这只是一种观点。

对此没有行业共识,也没有更普遍的 Spring 持久性与 CMP 辩论。因此,这应该由您的组织彻底讨论。

理想情况下,应该以客观的方式记录利弊,并通过现实世界的证据进行权衡。只有这样,您的组织才能做出明智的决定,并且您应该坚持这样做。

不幸的是,有些人有“坚定的信念”(也就是强烈的意见),他们偏爱一个。恕我直言,更好的建筑师正在等待基于证据的结果。

意见本质上是基于收集、解释和基于时间的信息(意思是意见会随着时间的推移而变化,因为收集到更多信息并提高理解。)这是 IT 中的一个常见问题(恕我直言),决策是基于少看证据,多看最有影响力的人的意见。

我观察到许多人将意见与事实混为一谈。

一些 IT 领导者(例如 Venkat Subramaniam)警告不要过度使用注释,因为它们会将您的代码与特定的实现相结合。您的代码使用了大量注释。

Spring 框架的好处之一是大多数类都没有对 Spring 的引用,并且是完全解耦的。业界普遍认为,去耦可以降低维护成本。

Spring 将配置从代码移动到外部 (XML) 配置文件。这被广泛认为是应用程序架构发展中的积极一步。

Grails 和 Ruby on Rails 框架迈出了下一步,通过“约定优于配置”消除了大部分配置文件。

查看代码片段的一种方法是将它们还原为两代,成为紧密耦合的解决方案(具有讽刺意味的是,为了利用“新”技术。)

同样,这只是一种观点。但我发现,在实践中,很少有组织会客观地权衡利弊。

于 2013-03-05T07:28:45.310 回答
0

如果您想使用休眠将用户域对象存储在数据库中 - 您只需调用em.persist(user)某处。将持久性操作包装在数据访问层中被认为是一种很好的做法。数据访问层用于EntityManager执行常见的持久性操作,如保存、查找、删除、列表、计数......)并使用EntityManager. 上面的数据访问层应该是提供与您的应用程序相关的业务方法的事务服务层,例如UserService与方法createUserAccount- 服务层调用数据访问层来执行基本操作(例如在事务中保存用户并为他分配一些安全角色)。最后,应用程序中的控制器应该只与服务层通信——这样你就可以从低级 ORM API 中抽象出来。

于 2013-03-04T19:02:43.050 回答