実験に必要なものはすべて準備します。 データベースから始めましょう。 まず、練習用のタブレットを3つ作成します。
CREATE TABLE book ( id NUMBER NOT NULL, name VARCHAR2 (100 BYTE) NOT NULL, description VARCHAR2 (1000 BYTE) NOT NULL, CONSTRAINT pk$book_id PRIMARY KEY (id) ) CREATE TABLE student ( id NUMBER NOT NULL, name VARCHAR2 (100 BYTE) NOT NULL, CONSTRAINT pk$student_id PRIMARY KEY (id) ) CREATE TABLE catalog ( id_student NUMBER NOT NULL, id_book NUMBER NOT NULL )
次に、関数を作成します。 idで本のタイトルを返す、例は愚かですが、入力数値パラメーターと出力文字列を使用して関数を呼び出す原理を示します。
CREATE OR REPLACE FUNCTION get_book_name_by_id (p_id IN NUMBER) RETURN VARCHAR2 IS v_name VARCHAR2 (100); BEGIN SELECT name INTO v_name FROM book WHERE id = p_id; RETURN v_name; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN ' !!'; END;
また、実験として、データベースに単純な保存プロシージャを作成します。このプロシージャには、入力パラメータと出力パラメータの両方が含まれます。
CREATE OR REPLACE PROCEDURE save_book (p_id IN OUT NUMBER, p_name IN VARCHAR2, p_descr IN VARCHAR2) IS BEGIN IF p_id > 0 THEN UPDATE book SET name = p_name, description = p_descr WHERE id = p_id; ELSE SELECT catalog_seq.NEXTVAL INTO p_id FROM DUAL; INSERT INTO book VALUES (p_id, p_name, p_descr); END IF; END;
それでは、Javaのクラスに移りましょう。
次のように、クラスに3つのデータベーステーブルを表示します。
@Entity @Table public class Student implements Serializable { private static final long serialVersionUID = -5170875020617735653L; @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "my_entity_seq_gen") @SequenceGenerator(name = "my_entity_seq_gen", sequenceName = "catalog_seq") private long id; @Column private String name; @OneToMany(mappedBy = "student", fetch = FetchType.LAZY) private Set<Book> bookList; // getter, setter, hashCode(), equals(), toString() }
コードに関する簡単な説明:
- クラス名がテーブルの名前と一致しない場合、たとえば次のように記述します。Table(name = "STUDENT");
- フレームワークの要件の1つは、各テーブルにidが必要であることです。また、テーブルのidフィールドの名前と変数の名前が一致しない場合、アノテーションは次のようになります。Id @Column(name = "table id in the database");
- アノテーション@GeneratedValueおよび@SequenceGeneratorを使用して、一意の識別子を生成するための戦略を決定します。この場合、データベースに情報を保存するときに、「catalog_seq」という名前のシーケンスから番号を取得します。
- 1人の生徒に複数の本を持たせることができるので、@ OneToMany(mappedBy = "student"、fetch = FetchType.LAZY)のようなアノテーションを使用してこれを表示します。mapedBy= "student"はBookクラスのフィールド名です(参照以下)、およびFetchType.LAZY-コレクションが
Set<Book> bookList
次の2つのデータベーステーブルのマッピングは次のようになります。
@Entity @Table public class Book implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name="ID") @GeneratedValue(strategy = GenerationType.AUTO, generator = "my_entity_seq_gen") @SequenceGenerator(name = "my_entity_seq_gen", sequenceName = "catalog_seq") private long id; @Column(name="NAME",unique = true, nullable = false, length = 100) private String name; @Column(name="DESCRIPTION",unique = true, nullable = false, length = 100) private String description; @ManyToOne(fetch = FetchType.LAZY,optional=true) @JoinTable(name = "CATALOG", joinColumns = @JoinColumn(name = "ID_BOOK"), inverseJoinColumns = @JoinColumn(name = "ID_STUDENT")) private Student student; // getter, setter, hashCode(), equals(), toString() }
フィールドの制限はアノテーションで直接設定できます。これは、次の行@Column(名前= "NAME"、一意= true、nullable = false、長さ= 100)によって行われます。 注釈@ManyToOneおよび@JoinTable(name =“ CATALOG”)を使用すると、BookテーブルとStudentテーブルはCatalogテーブルを介して多対多の関係を持つため、BookとStudentへのすべての変更は自動的に適用されますカタログ表。
さて、マッピングテーブルの処理は完了しました。次に、データベースを直接操作する方法に進みます。
コレクションを埋めながらデータを抽出するには、さまざまな方法があります。
- HQL(Hibernate Query Language)クエリの使用
List<Book> book = (List<Book>)session.createQuery("from Book order by name").list();
- SQLクエリを使用する
List<Book> book = (List<Book>)session.createSQLQuery("select ID, DESCRIPTION, NAME from book order by NAME") .addScalar("id",Hibernate.LONG).addScalar("name").addScalar("description") .setResultTransformer(Transformers.aliasToBean(Book.class)).list();
- 基準付き
List<Book> book=(List<Book>)session.createCriteria(Book.class).createAlias("student", "st").add(Restrictions.eq("st.name", "Maxim")).list();
ストアドプロシージャの使用に移りましょう。 IDで本のタイトルを返す関数を呼び出すには、次の手順を実行します。
String bookName = (String)session.createSQLQuery("{? = call get_book_name_by_id (:id)}").setLong("id",1).uniqueResult();
Studentというテーブルがサーバー上にないが、カーソルを返す関数のみがあるとします。
FUNCTION get_all_students RETURN SYS_REFCURSOR IS l_cur SYS_REFCURSOR; BEGIN OPEN l_cur FOR SELECT * FROM student ORDER BY 1; RETURN l_cur; END;
次に、 @Table(name="STUDENT")
に注釈を付ける代わりに、次のようにマッピングが行われます。
@NamedNativeQuery(name="getAllStudent",query="{? = call get_all_students}", callable=true, resultClass=Student.class)
そして、この関数の呼び出しは次のようになります。 List<Student> student = (List<Student>) session.getNamedQuery("entity").list();
さて、save_bookプロシージャを呼び出すには、次の操作を行います。
CallableStatement st = session.connection().prepareCall("{call save_book(?,?,?)}"); st.setLong(1,0); st.setString(2, " , "); st.setString(3,"- "); st.registerOutParameter(1, java.sql.Types.NUMERIC); st.execute(); System.out.println(st.getLong(1));
お気づきかもしれませんが、データベースにアクセスしてコレクションにデータを入力するコマンドを作成するときには、セッションという言葉が使用されていました。 私たちの場合、この単語は、JavaアプリケーションとHibernateフレームワークの間のメインインターフェース、つまりorg.hibernate.Sessionセッションを示しています。 しかし、最初に、別の基本的かつ重要なインターフェースであるSessionFactoryを使用する必要があります。 SessionFactoryは、特定のデータベースを担当するグローバルファクトリです。 このファクトリを取得するには、org.hibernate.cfg.Configurationクラスのインスタンスを取得する必要があります。 これは次のように行われます。 SessionFactory sessions = new Configuration().configure().buildSessionFactory();
Where Configuration()。Configure()。BuildSessionFactory()は、パスが指定されていない場合はもちろん、呼び出されるプログラムの隣にあるhibernate.cfg.xmlというファイルを解析します。 データベースへの接続の構成と表の表示を示す構成ファイルは次のとおりです。
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:port:baseName</property> <property name="hibernate.connection.username">username</property> <property name="hibernate.connection.password">password</property> <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property> <property name="show_sql">true</property> <mapping class="com.sample.javaHibernate.data.Book" /> <mapping class="com.sample.javaHibernate.data.Student" /> </session-factory> </hibernate-configuration>
そして今、必要なすべての構成(プールを介したデータベースへの接続、テーブルのマッピング/表示など)が存在するファクトリーがあれば、Sessionで作業できます。 次のようなトランザクションを使用できますSession session = sessions.openSession();
session.beginTransaction();
したがって、
session.getTransaction().commit();
すべてのようです。 もちろん、すべてをカバーすることはできませんでしたが、クイックスタートにはこれで十分だと思います。