S2Dao.NET TOPページへ
S2Dao.NET - Entityクラス
Entityクラスはテーブルとの関連付けに使用します。
Entityクラスにはテーブルのカラムとマッピングするためのプロパティを実装します。
場合によってはEntityクラスに以下の属性の指定が必要になります。S2Dao.NETで使用する属性は Seasar.Dao.Attrs名前空間にあります。
Entityクラスにはテーブルのカラムに対応したフィールドとプロパティを宣言・実装します。クラス名(名前空間名を除く)は可能であればテーブル名と同じに、
プロパティ名は可能であればテーブルのカラム名と同じにすると良いでしょう。
カラムがNull可の場合、プリミティブ型(System.Int32等)を指定するとNullの際、0(ゼロ)が返されます。
Nullを扱うためには.NET Framework 2.0からのnull許容型(System.Nullable構造体)、System.Data.SqlTypes名前空間のデータ型を指定して下さい。
例えば、EMPテーブルに関連付くEntityクラスは次のようになります。
C#
using System;
using Seasar.Dao.Attrs;
namespace MyNamespace
{
[Table("EMP")]
public class Employee
{
private int empno;
private string ename;
private short deptnum;
public Employee()
{
}
public int Empno
{
set { empno = value; }
get { return empno; }
}
public string Ename
{
set { ename = value; }
get { return ename; }
}
public short Deptnum
{
set { deptnum = value; }
get { return deptnum; }
}
}
}
VB.NET
Imports System
Imports Seasar.Dao.Attrs
Namespace MyNamespace
<Table("EMP")> _
Public Class Employee
Private empno As Integer
Private ename As String
Private deptnum As Short
Public Sub New()
End Sub 'New
Public Property Empno() As Integer
Get
Return empno
End Get
Set
empno = value
End Set
End Property
Public Property Ename() As String
Get
Return ename
End Get
Set
ename = value
End Set
End Property
Public Property Deptnum() As Short
Get
Return deptnum
End Get
Set
deptnum = value
End Set
End Property
End Class
End Namespace
テーブルとの関連付けはTable属性を使用します。Table属性はクラスに指定します。
Table属性にはテーブル名を指定します。スキーマ名も指定する場合は"スキーマ名.テーブル名"と指定します。
※ クラス名(名前空間名は除く)とテーブル名が一致(大文字小文字は区別しない)する場合は、Table属性を省略することが出来ます。
EMPテーブルの場合は以下のようになります。
C#
[Table("EMP")]
public class Employee
VB.NET
<Table("EMP")> _
Public Class Employee
テーブルのカラムとの関連付けはColumn属性を使用します。Column属性はプロパティに指定します。Column属性にはカラム名を指定します。
※ プロパティ名とカラム名が一致(大文字小文字は区別しない)する場合は、Column属性を省略することが出来ます。
テーブルに存在しないプロパティは自動的に無視されます。
EmployeeNoというプロパティにEMPNOカラムを関連付ける場合は以下のようになります。
C#
[Column("EMPNO")]
public int EmployeeNo
{
set { _employeeNo = value; }
get { return _employeeNo; }
}
VB.NET
<Column("EMPNO")> _
Public Property EmployeeNo() As Integer
Get
Return _employeeNo
End Get
Set
_employeeNo = value
End Set
End Property
N:1マッピングとは、複数の従業員の行に1つの部署の行が関連付けられるような場合のマッピングです。
N:1マッピングを利用するには、Relno属性とRelkeys属性をそれぞれ指定する必要があります。
Relno属性とRelkeys属性を指定すると、
検索SQLの自動生成を行う場合に左外部結合(LEFT OUTER JOIN)を自動的に行います。
Relno属性とRelkeys属性は結合先となるEntityクラス型で作成したプロパティに指定します。
Relno属性はN:1マッピングの0(ゼロ)から始まる連番を指定します。
例えば、AAAのテーブルにBBB, CCCのテーブルがN:1マッピングされるとするとBBBのRelno属性には0を、
CCCのRelno属性には1を指定します。
また、Relno属性は結果セットに含まれているカラムが、どのテーブルに属しているのかを判定することにも使われます。
これはSQL属性やSQLファイルを用いて手動でSQLを記述する際に利用します。
例えば、SELECT ..., BBB.HOGE AS HOGE_0, ... FROM AAA, BBB ...のようなSELECT文があった場合、
HOGE_0はBBBテーブルに含まれているHOGEカラムであると認識され、結果が結合先のEntityクラスの対応するプロパティにセットされます。
N:1マッピングのキーはRelkeys属性で指定します。キーが複数ある場合には、カンマ(,)で区切ります。
例えば "mykey1:yourkey1,myke2:yourkey2"のようにします。
EMPテーブルのDEPTNUMカラムとDEPTテーブルのDEPTNOを関連付ける場合は以下のようになります。
C#
[Relno(0), Relkeys("DEPTNUM:DEPTNO")]
public Department Department
{
set { _department = value; }
get { return _department; }
}
VB.NET
<Relno(0), Relkeys("DEPTNUM:DEPTNO")> _
Public Property Department() As Department
Get
Return _department
End Get
Set
_department = value
End Set
End Property
1側のテーブルのカラム名がN側のテーブルのカラム名に等しい場合は、1側のテーブルのカラム名を省略することが出来ます。
その場合は以下のように定義します。
C#
[Relno(0), Relkeys("DEPTNO")]
VB.NET
<Relno(0), Relkeys("DEPTNO")>
また1側のテーブルのカラム名とN側のテーブルのカラム名が等しく、1側のテーブルのカラム名がプライマリキーの場合、
Relkeys属性を省略することが出来ます。
ID(プライマリキー)をRDBMSに自動生成させて、自動生成させた値をEntityに自動的に設定することが出来ます。
そのために使うのが、ID属性です。ID属性を指定してS2Dao.NETにInsert文を作成させた場合、
引数で渡したEntityのID属性が指定されたプロパティに、RDBMSによって自動生成された値がセットされます。
ID属性の値は、文字列またはIDType列挙型で指定します。
ID属性はプロパティに指定します。
C#
[ID("identity")]
public int ID
{
set { _id = value; }
get { return _id; }
}
[ID(IDType.IDENTITY)]
public int ID
{
set { id = value; }
get { return id; }
}
VB.NET
<ID("identity")> _
Public Property ID() As Integer
Get
Return _id
End Get
Set
_id = value
End Set
End Property
<ID(IDType.IDENTITY)> _
Public Property Id() As Integer
Get
Return _id
End Get
Set
_id = value
End Set
End Property
SEQUENCEを使うことも出来ます。myseqの部分は、実際のSEQUENCEに置き換えて下さい。
C#
[ID("sequence", "myseq")]
[ID(IDType.SEQUENCE, "myseq")]
VB.NET
<ID("sequence", "myseq")>
<ID(IDType.SEQUENCE, "myseq")>
手動でIDを設定する場合は、何も指定する必要はありません。テーブルのプライマリキーの情報はテーブル定義より自動的に取得されます。
また、明示的に"assigned"を指定することも出来ます。
C#
[ID("assigned")]
[ID(IDType.ASSIGNED)]
VB.NET
<ID("assigned")>
<ID(IDType.ASSIGNED)>
ID属性の複数DBMS対応
DBMS毎に使用するID属性を指定することができます。どのDBMSを使っているのかは、
Diconファイルに登録されているデータプロバイダとS2Dao.NETが持っているDbms.resxからS2Dao.NETが自動的に判断しています。
DBMS毎にID属性を用意する場合は、ID属性の第3引数にSeasar.Dao.KindOfDbms列挙型でDBMSを指定します。
KindOfDbms列挙型の一覧は、Sql属性の複数DBMS対応を参照してください。
C#
[ID(IDType.SEQUENCE, "myseq", KindOfDbms.Oracle)]
VB.NET
<ID(IDType.SEQUENCE, "myseq", KindOfDbms.MSSQLServer)>
Entityクラスのプロパティが永続化(テーブルとマッピング)の対象かどうかという情報は、
テーブルの定義より自動的に取得されます。また、明示的にNoPersistentProps属性を使って永続化したくないプロパティを指定することもできます。
NoPersistentProps属性はクラスに指定します。引数に永続化しないプロパティ名を指定します。
引数は可変個引数となっており、複数のプロパティ名を指定することが出来ます。(C#でいうparamsキーワード指定, VBでいうParamArrayキーワード指定)
Property1とProperty2というプロパティを永続化したくない場合は以下のようになります。
C#
[NoPersistentProps("Property1", "Property2")]
public class Employee
VB.NET
<NoPersistentProps("Property1", "Property2")> _
Public Class Employee
S2Dao.NETはEntityクラスにSystem.Int32型でVersionNoという名前のプロパティを定義するだけで、
VersionNoによる排他制御を自動的に行ってくれます。
VersionNoによる排他制御は、S2Dao.NETに自動で更新(UPDATE, DELETE)SQL文を作成させた場合に行われます。
またDaoインターフェースの更新メソッドに渡すEntityには、VersionNoプロパティに値がセットされている必要があります。
例えば、2人のユーザがVersionNoの値が0である同一データを取得して更新しようとした場合、先に更新したユーザは正常に登録することが出来ます。
そのとき自動でVersionNoの値はインクリメント(+1)され、データベースのVersionNoの値は1となります。
次にもう1人のユーザが更新しようとすると、ユーザが保持しているVersionNoの値(0)と、実際にデータベースに格納されているVersionNoの値(1)が異なることになり、
Seasar.Dao.NotSingleRowUpdatedRuntimeExceptionが発生し更新に失敗することになります。
VersionNoによる排他制御用のプロパティ名をデフォルトのVersionNoから変えるときには、VersionNoProperty属性を使用します。
VersionNoProperty属性はクラスに指定します。"MyVersionNo"という名前のプロパティを排他制御用のプロパティに指定する場合は以下のようになります。
C#
[VersionNoProperty("MyVersionNo")]
public class Employee
VB.NET
<VersionNoProperty("MyVersionNo")> _
Public Class Employee
S2Dao.NETはVersionNoの他にもTimestampによる排他制御も自動的に行うことができます。
System.DateTime型でTimestampという名前のプロパティを定義するだけで、Timestampによる排他制御を自動的に行ってくれます。
Timestampによる排他制御は、S2Dao.NETに自動で更新(UPDATE, DELETE)SQL文を作成させた場合に行われます。
またDaoインターフェースの更新メソッドに渡すEntityには、Timestampプロパティに値がセットされている必要があります。
S2Dao.NETに自動で追加(INSERT)SQL文を作成させた場合、現在日時がTimestampプロパティにセットされ、
Insert文が発行されます。
更新(Update, Delete)時にEntityのTimestampプロパティとデータベースのTimestampカラムの値を比較し、
異なっている場合にはVersionNoと同様にSeasar.Dao.NotSingleRowUpdatedRuntimeExceptionが発生します。
Timestampによる排他制御用のプロパティ名をデフォルトのTimestampから変えるときには、TimestampProperty属性を使用します。
TimestampProperty属性はクラスに指定します。"MyTimestamp"という名前のプロパティを排他制御用のプロパティに指定する場合は以下のようになります。
C#
[TimestampProperty("MyTimestamp")]
public class Employee
VB.NET
<TimestampProperty("MyTimestamp")> _
Public Class Employee
ODP.NET使用時のTimestampカラムの型
DBMSにOracle、データプロバイダにODP.NET(Oracle Data Provider .NET)を使用する場合、
System.DateTime型のTimestampプロパティに対応するデータベースのTimestampカラムの型はTIMESTAMP(7)~TIMESTAMP(9)を使用してください。
これは、データベースのTimestampカラムの型がTIMESTAMP(7)未満の場合、
System.DateTime型の値が切り捨てられて格納されるため、
更新(Update, Delete)時にEntityのTimestampプロパティとデータベースのTimestampカラムの値が常に異なり
Seasar.Dao.NotSingleRowUpdatedRuntimeExceptionが発生するためです。
|