0

em.persist() を書くのはもう好きではありません。新しいインスタンスを返すときにこれを行うことはできますか?

うーん、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

これを行う1つの方法は、ルートオブジェクトからのカスケードを使用することです。あなたの場合、おそらくUsersはに属しDepartmentます。そのクラスに、マークされたへの@OneToManyマッピングを与えることができます:UserCascadeType.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のようなsの自然な集約がない場合はDepartment、すべてのユーザーに対して単一のマスタールートオブジェクトを作成できます。または、ユーザーをタイプ(管理者、顧客、作成者など)に分類しUserType、そのタイプのすべてのユーザーのコレクションを使用して、それぞれにインスタンスを作成することもできます。

最後に、このアプローチは技術的には可能ですが、通常は良い考えではないと思います。複数のスレッドがルートオブジェクトのコレクションを同時に更新すること(トランザクションコミットの失敗として現れる可能性があります)、またはこれらの巨大なコレクションをメモリにロードすること(これは必要ではないはずですが、とにかく発生する可能性があります)に関連する問題に遭遇することに神経質になります)。

于 2013-03-04T20:06:42.073 に答える
1

em.persist:) の使用を取り除くことができAOPます。関数が実行された後、em.persist()それが返すものは何でも実行するために自分自身の注釈を付けることができます :)。

あなたはできる :

  1. java eeの場合に備えてインターセプターを作成します...
  2. spring を使用する場合は、aspectjまたは AOP を使用します
  3. いくつかDAOの を使用してオブジェクトを操作する

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

はい、できます。さらに、次のことができます。

  • より少ないコードで同じ機能を実現する
  • より単純なコードで同じ機能を実現する
  • 読みやすいコードで同じ機能を実現する
  • 理解しやすいコードで同じ機能を実現する
  • より生産的になる
  • カップリングを減らす (これにより、コードの維持費が安くなります)

これらはすべて、CMP ではなく GORM を使用して取得できます。これは一点にすぎませんのでご注意ください。

これに関する業界のコンセンサスはなく、Spring の永続性と CMP のより一般的な議論もありません。したがって、これについては組織内で十分に検討する必要があります。

理想的には、長所と短所を客観的な方法で文書化し、実際の証拠によって比較検討する必要があります。そうして初めて、組織は情報に基づいた決定を下すことができ、それを主張する必要があります。

残念なことに、どちらか一方を支持する「固い信念」(別名、強い意見) を持つ人々がいます。私見より優れたアーキテクトは、証拠に基づく結果を待っています。

意見は、本質的に、収集、解釈、および時間ベースの情報に基づいています (より多くの情報が収集され、理解が向上するにつれて、意見は時間の経過とともに変化することを意味します)。証拠ではなく、最も影響力のある人々の意見に重点を置いています。

多くの人が意見と事実を混同しているのを私は見てきました。

一部の IT リーダー (Venkat Subramaniam など) は、アノテーションを過度に使用しないように警告しています。これは、コードが特定の実装に結び付けられるためです。コードで多数の注釈が使用されています。

Spring フレームワークの利点の 1 つは、ほとんどのクラスが Spring を参照せず、完全に分離されていることです。業界では、デカップリングによって保守コストが削減されるという点で広く一致しています。

Spring は構成をコードから外部 (XML) 構成ファイルに移動しました。これは、アプリケーション アーキテクチャの進化における前向きな一歩と広く見なされていました。

Grails および Ruby on Rails フレームワークは次のステップに進み、「設定より規約」によって設定ファイルの大部分を排除します。

コード スニペットを表示する 1 つの方法は、密結合されたソリューションに 2 世代前に戻すことです (皮肉なことに、「新しい」テクノロジを利用するためです)。

繰り返しますが、これは 1 つの意見にすぎません。しかし、実際には、長所と短所を客観的に比較検討している組織はほとんどありません。

于 2013-03-05T07:28:45.310 に答える
0

休止状態を使用してユーザー ドメイン オブジェクトをデータベースに格納する場合は、単にどこかを呼び出す必要がありますem.persist(user)。永続的な操作をデータ アクセス レイヤーでラップすることをお勧めします。データ アクセス レイヤーはEntityManager、保存、検索、削除、リスト、カウントなどの一般的な永続操作を実行するために使用し、 EntityManager. データ アクセス レイヤーの上には、アプリケーションに関連するビジネス メソッド (メソッドなど) を提供するトランザクションサービス レイヤーが必要です。UserServicecreateUserAccount- サービス層はデータ アクセス層を呼び出して基本的な操作を実行します (たとえば、トランザクション内でユーザーを保存し、いくつかのセキュリティ ロールを割り当てます)。最後に、アプリケーションのコントローラーはサービス層とのみ通信する必要があります。このようにして、低レベルの ORM API から抽象化できます。

于 2013-03-04T19:02:43.050 に答える