Hibernate:SQLクエリーの名前付け

6575 ワード

名前付きSQLクエリーは、その名前の通り、SQL文をプログラムから抽出し、注釈で管理し、各SQLクエリーに名前を付けます.プログラムではこの名前を呼び出すだけで、プログラムのデカップリングを向上させることができます.
Hibernateでは、@NamedNativeQuery注記を使用して名前付きのオリジナルSQLクエリーを定義できます.複数の名前付きクエリーがある場合は、@NamedNativeQueries注記を使用して管理できます.
次の@NamedNativeQuery注記でサポートされているプロパティ:
name:SQLクエリーの名前を指定するには、プロパティが必要です.
query名前付きSQLクエリを指定するクエリ文に属性が必要
resultClassは、addEntity()と同様に、単純なクエリーでクエリー結果を指定したエンティティクラスのインスタンスにマッピングします.必須でない属性
resultSetMappingこの属性はSQL結果マッピングの名前を指定します(この結果マッピングは@SqlResultSetMapping定義を使用する必要があります).
            この結果マッピングを使用して、クエリー結果セットを変換します.
単純なクエリーではresultClassを使用してクエリーの結果を対応するエンティティに変換できますが、クエリーのデータ列が多く、プログラムがスカラークエリー、エンティティクエリーを同時に行う場合はresultSet Mappingを使用する必要があります.
@NamedNativeQuery注記を使用してresultSetMappingプロパティを指定する必要がある場合(つまり複雑なクエリーが必要な場合)は、@SqlResultSetMappingを使用してSQL結果マッピングを定義する必要があります.@SqlResultSetMappingの役割は、SQLQueryオブジェクトのaddScale()またはaddEntity()メソッドのようなクエリーの結果セットをスカラークエリーまたはエンティティクエリーに変換する機能です.
resultSetMappingと@SqlResultSetMappingの両者は混同されやすいかもしれませんが、何をしているのか分かりません.一般的には@SqlResultSetMappingは結果マッピングルールを制定したもので、結果セットはスカラークエリに変換されたのか、エンティティクエリに変換されたのか、私が制定したものです.resultSetMappingは、上記のマッピング名によってこの結果を参照してマッピングされます.
@SqlResultSetMappingでサポートされているプロパティを次に示します.
name SQL結果マッピングの名前(前述のresultSetMapping参照)に必要なプロパティを指定します.
columnsこの属性の値は@ColumnResult注記配列であり、各@ColumnResult注記はスカラークエリーを定義する
Entitiesこの属性の値は@EntityResult注記配列であり、各@EntityResult注記はエンティティクエリーを定義します.
classこの属性の値は@ConstructorResult注記配列で、各@ConstructorResultは指定した複数の列を通常のクラスに変換する責任を負います.    ツールバーの
上記の@ColumnResult注記はSQLQueryオブジェクトのaddScalar()と同様に結果セットをスカラークエリに変換し、いくつかの@ColumnResult注記はSQLQueryのaddScalar()メソッドを数回呼び出すことに相当します.
同様に@EntityResult注記はSQLQueryオブジェクトのaddEntity()と同様に結果セットをスカラークエリに変換し、いくつかの@EntityResult注記はSQLQueryのaddEntity()メソッドを数回呼び出すことに相当します.
次に例を示します.
一:まずresultClassで結果変換を完了できる簡単なクエリー
//       SQL  ,    simpleQuery
@NamedNativeQuery(name="simpleQuery"
	//     SQL     SQL  
	, query="select s.student_id , s.name from student_inf s"
	//           Student  
	, resultClass=Student.class)
@Entity
@Table(name="student_inf")
public class Student
{
	//            ,       
	@Id @Column(name="student_id")
	private Integer studentNumber;
	//            
	private String name;
	//                  
	@OneToMany(targetEntity=Enrolment.class
		, mappedBy="student" , cascade=CascadeType.REMOVE)
	private Set enrolments
		= new HashSet<>();

	//        
	public Student()
	{
	}
	//              
	public Student(Integer studentNumber , String name)
	{
		this.studentNumber = studentNumber;
		this.name = name;
	}

	// studentNumber setter getter  
	public void setStudentNumber(Integer studentNumber)
	{
		this.studentNumber = studentNumber;
	}
	public Integer getStudentNumber()
	{
		return this.studentNumber;
	}

	// name setter getter  
	public void setName(String name)
	{
		this.name = name;
	}
	public String getName()
	{
		return this.name;
	}

	// enrolments setter getter  
	public void setEnrolments(Set enrolments)
	{
		this.enrolments = enrolments;
	}

この例では、@NamedNativeQueryによってsimpleQueryのSQLクエリーを定義します.このクエリーは簡単なので、
@NamedNativeQueryのresultClassプロパティは、結果セットをStudentエンティティにマップすればよいので、この名前付きクエリーで得られる結果は、集合要素Studentのリストセットである必要があります.
以下の方法で、上記の名前のSQLクエリーを実行できます.
public class NamedSQLTest
{
	public static void main(String[] args)
	{
		NamedSQLTest test = new NamedSQLTest();
	       test.simpleQuery();
		HibernateUtil.sessionFactory.close();
	}

	//        SQL  
	private void simpleQuery()
	{
		//   Session   
		Session session = HibernateUtil.currentSession();
		Transaction tx = session.beginTransaction();
		//       ,      
		List list = session.getNamedQuery("simpleQuery")
			.list();
		tx.commit();
		HibernateUtil.closeSession();
		//      
		for(Object ele : list)
		{
			//        Student  
			Student s = (Student)ele;
			System.out.println(s.getName() + "\t");
		}
	}
}

二:スカラークエリー、エンティティクエリーに基づく複雑なクエリー
まず、複雑な名前付きSQLクエリーを定義します.
//       SQL  ,    queryTest
@NamedNativeQuery(name="queryTest"
	//   SQL  
	, query="select s.*,e.*,c.* from student_inf s,enrolment_inf e,"
	+ " course_inf c where s.student_id = e.student_id and"
	+ " e.course_code = c.course_code and e.year=:targetYear"
	//       firstMapping @SqlResultSetMapping      
	, resultSetMapping = "firstMapping")

このクエリ文は複雑で、クエリデータ列が多いため、firstMapping結果マッピングを使用して結果セットの変換を担当します.ここではfirstMappingという名前の結果マッピングを使用します.以下は
FirstMapping結果マッピングの定義:
@SqlResultSetMapping(name="firstMapping"
			,entities={@EntityResult(entityClass=Student.class),
					@EntityResult(entityClass=Enrolment.class),
					@EntityResult(entityClass=Course.class,fields=
						{
								@FieldResult(name="id" , column="c.course_code"),
								@FieldResult(name="name" , column="c.name")
							}
					
							)}
	      ,columns={@ColumnResult(name="s.name" ,type=String.class)}
	)

@SqlResultSetMappingによって定義された
firstMapping結果マッピング、entitiesで@EntityResult注記を3つ指定し、columnsで@ColumnResultを指定します.これは、SQLクエリに3つのエンティティクエリ、1つのスカラークエリが含まれていることを示します.
次の方法では、SQLクエリーの名前を指定できます.
public class NamedSQLTest
{
	public static void main(String[] args)
	{
		NamedSQLTest test = new NamedSQLTest();
		test.query();
		HibernateUtil.sessionFactory.close();
	}



	//     SQL  
	private void query()
	{
		//   Session   
		Session session = HibernateUtil.currentSession();
		Transaction tx = session.beginTransaction();
		//       ,      
		List list = session.getNamedQuery("queryTest")
			.setInteger("targetYear" , 2005)
			.list();
		tx.commit();
		HibernateUtil.closeSession();
		//      
		for(Object ele : list)
		{
			//        Student、Enrolment
			//  stuName       
			Object[] objs = (Object[])ele;
			Student s = (Student)objs[0];
			Enrolment e = (Enrolment)objs[1];
			Course c = (Course)objs[2];
			String stuName = (String)objs[3];
			System.out.println(s.getName() + "\t"
				+ e.getYear() + "\t" + e.getSemester()
				+ "\t=" + e.getCourse().getName() + "=\t" + stuName);
		}
	}
}

ここでは、返される結果の集合が表示されます.各集合要素はいくつかのエンティティからなる配列です.ここで、最初の3つの配列要素は私たちが定義した3つのエンティティクエリーであり、4番目の配列要素は私たちが定義したスカラークエリーを使用します.
また、@NamedNativeQueryを複数定義する必要がある場合は、@NamedNativeQueries({})を使用して管理します.
    複数の@SqlResultSetMappingを定義する必要がある場合は、@SqlResultSetMappings({})を使用して管理します.