Seasar - DI Container with AOP -
Seasar DI Container with AOP
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属性にはテーブル名を指定します。スキーマ名も指定する場合は"スキーマ名.テーブル名"と指定します。

※ クラス名(名前空間名は除く)とテーブル名が一致(大文字小文字は区別しない)する場合は、Table属性を省略することが出来ます。

EMPテーブルの場合は以下のようになります。

C#
[Table("EMP")]
public class Employee
VB.NET
<Table("EMP")> _
Public Class Employee

カラムとの関連付けを行うColumn属性

テーブルのカラムとの関連付けは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

別テーブルとの結合を指定するRelno属性, Relkeys属性(N:1マッピング)

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の自動生成を指定するID属性

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)>

永続化されないカラムを指定するNoPersistentProps属性

Entityクラスのプロパティが永続化(テーブルとマッピング)の対象かどうかという情報は、 テーブルの定義より自動的に取得されます。また、明示的にNoPersistentProps属性を使って永続化したくないプロパティを指定することもできます。

NoPersistentProps属性はクラスに指定します。引数に永続化しないプロパティ名を指定します。 引数は可変個引数となっており、複数のプロパティ名を指定することが出来ます。(C#でいうparamsキーワード指定, VBでいうParamArrayキーワード指定)

Property1とProperty2というプロパティを永続化したくない場合は以下のようになります。

C#
[NoPersistentProps("Property1", "Property2")]
public class Employee
VB.NET
<NoPersistentProps("Property1", "Property2")> _
Public Class Employee

VersionNoによる排他制御とVersionNoProperty属性

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

Timestampによる排他制御とTimestampProperty属性

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が発生するためです。