论坛首页 入门技术论坛

EJB3(中文版) 第九集 基本属性映射

浏览 2976 次
该帖已经被评为新手帖
作者 正文
   发表时间:2006-11-04  
动画中用到的注释:
@Table注释
@javax.persistence.Table注释告诉EntityManager服务关系表映射成组件类,
你不需要详细指定这个注释,如果你不想映射,表名是无限制的组件类名.让我们看一下这个注释的完整定义:
package javax.persistence;
@Target({TYPE}) @Retention(RUNTIME)
public @interface Table
{
   String name( ) default "";
   String catalog( ) default "";
   String schema( ) default "";
   UniqueConstraint
uniqueConstraints( ) default {};
}
catalog( ) 和 schema( )属性是自省的,同样的它们识别有关表的catalog 和 schema属于:
public @interface UniqueConstraint
{
   String[] columnNames( );
}
@Table.uniqueConstraints( )属性允许指定唯一的栏限制那将被包含在数据库定义语言(DDL)中,一些提供商的工具能够创建DDLs通过实体类集合,或自动表生成,当组件被部署时,UniqueConstraint注释非常的有用在使用特定提供商定义额外的约束时,如果你不使用schema生成工具,你不需要定义这片元数据.
@Table 和 @UniqueConstraint注释有一个等价的XML映射元素:
<table name="CUSTOMER_TABLE" catalog="TITAN" schema="TITAN">
   <unique-constraint>
      <column-name>SOME_OTHER_ATTRIBUTE</column_name>
   </unique-constraint>
</table>
<table>元素是<entity>元素的子元素,如果你需要可以指定多个<unique-constraint>元素,一个唯一性约束可以包含多个栏,倒不如多个唯一性约束.

@Column注释
使用@Column注释,我们需要设置id属性的栏位名为CUST_ID并且是非空,数据库中的类型是integer.firstName属性,我们改变了栏位名和VARCHAR类型的长度映射成20.
@javax.persistence.Column注释描述详细的字段和属性信息映射到表中的指定栏:
public @interface Column
{
   String name( ) default "";
   boolean unique( ) default false;
   boolean nullable( ) default true;
   boolean insertable( ) default true;
   boolean updatable( ) default true;
   String columnDefinition( ) default "";
   String table( ) default "";
   int length( ) default 255;
   int precision( ) default 0;
   int scale( ) default 0;
}
name( )属性很明显的指定栏位名,如果你没有指定栏位名,栏位名默认的为字段或属性,table( )属性用来多表映射,在本章后将会介绍,其它的属性用来在厂商提供的工具自动生成Schema时使用.如果映射到一个已存在的schema,你不需要定义任何的这些属性,unique( ) and nullable( )属性定义约束在栏位上,你可以指定是否想要栏位被包含在SQL INSERT or UPDATE 使用 insertable( ) and updatable( ), 分别的.columnDefinition( )属性允许你定义准确的DDL来定义栏位类型,length( )属性确定VARCHAR类型的长度当有一个String类型的属性.
为了数值型属性你可以定义scale( ) 和precision( )属性.
@Column注释有一个等价的XML文件中的<column>元素,这个元素是属性映射类型<id>, <basic>, <temporal>, <lob>的子元素,<enumerated>元素的描述将会在本章后进行.
<basic name="lastName">
   <column name=""
           unique="true"
           nullable="true"
           insertable="true"
           updatable="true"
           column-definition=""
           table=""
           length=""
           precision=""
           scale=""
   />
</basic>
<column>元素的属性有相同和行为和默认值与@column注释.

@Id注释
@javax.persistence.Id注释标识一个或多个属性,来组成表中的主键:
package javax.persistence;

@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface Id
{
}
你可以通过手动或厂商提供的工具来生成主键,当你使用厂商提供的工具生成时你需要使用@javax.persistence.GeneratedValue,注释:
package javax.persistence;

@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface GeneratedValue
{
   GenerationType strategy( ) default AUTO;
   String generator( ) default "";
}

public enum GenerationType
{
   TABLE, SEQUENCE, IDENTITY, AUTO
}
持久化提供商要求提供键生成原始主键,你可以定义主键类型来生成通过strategy( )属性.GeneratorType.AUTO策略是一般的配置,AUTO策略告诉持久化提供者允许为你提供键.IDENTITY策略使用特殊栏类型,支持多种数据库,来建立主键.

@Basic注释
@Basic注释是最简单的映射形式对原持久化的属性来说.也是默认的属性映射类型是最原始的,原始的包装类型, java.lang.String, byte[], Byte[], char[], Character[], java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time , and java.sql.Timestamp.你不需要很明确的告诉持久化管理器映射成基本属性因为它通常计算出JDBC所使用的属性类型.

@Temporal注释(与时间相关的注释)
@Temporal注释提供额外的信息到持久化提供者关于映射java.util.Date 或 java.util.Calendar类型的属性.这个注释允许你映射这些种对象类型到一个日期,一个时间,或一个时间戳字段在数据库中.默认情况下,持久化提供者假定时间类型为一个时间戳,这个注释能够与@Basic注释联合使用.

@Lob注释
有时持久化属性需要很大的内存.字段中的一个代表一幅图片或一个非常大的文本.JDBC有特殊的类型与这些非常大的对象对应. java.sql.Blob类型代表二进制数据,和java.sql.Clob代表字符数据. @javax.persistence.Lob注释用来映射那些大的对象类型.JAVA持久化允许你映射一些基本类型到@Lob和持久化管理器处理他们内部的任一个Blob或Clob类型,依赖属性的类型:
package javax.persistence;

public @interface Lob
{
}
@Lob注释的属性持久化一个:
◆Blob 如果Java类型是byte[], Byte[], 或 java.io.Serializable
◆Clob如果Java类型是char[], Character[],或java.lang.String
@Lob注释常同@Basic注释联合使用提示属性将被延迟加载.让我们修改Customer组件来增加代表一个JPEG图象的属性.

@Enumerated 注释
@Enumerated注释映射Java枚举类型到数据库中.它与@Basic注释联合使用.

FetchType类型
public enum FetchType
{
   LAZY, EAGER
}
通常,不需要在持久化属性上指明这个注释.可是,有时你需要详细指明fetch()属性,当持久化对象第一次从数据库中取出时你需要详细指明装载的属性是延迟的还是热切的.这个属性在查询数据时允许持久化提共者优化数据库的访问使用最小的数据量进行装载.所以,如果fetch()属性是LAZY时,详细属性将不被初始化直到实际访问到这个字段时.所有的其它注释有同样的属性.这种不自然的事情在规范中,尽管fetch()这个属性是一个提示,即使你标记了属性为LAZY的@Basic类型,持久化的提供者仍然允计装载属性为热切的.实际上这是预期的这种特性是类级的工具.它将同样的被著名那个延迟装载的即不真正的有用也不是一个重要的执行优化.事实上最好是热切的装入基本属性.

常见异常:
Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
at $Proxy0.createCustomer(Unknown Source)
at com.lyh.ejb3.clients.Client.main(Client.java:38)
Caused by: java.rmi.MarshalException: Failed to communicate.  Problem during marshalling/unmarshalling; nested exception is:
java.io.NotSerializableException: com.lyh.ejb3.domain.Customer
at org.jboss.remoting.transport.socket.SocketClientInvoker.transport(SocketClientInvoker.java:306)
at org.jboss.remoting.RemoteClientInvoker.invoke(RemoteClientInvoker.java:143)
at org.jboss.remoting.Client.invoke(Client.java:525)
at org.jboss.remoting.Client.invoke(Client.java:488)
at org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemoteInterceptor.java:41)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
at org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPropagationInterceptor.java:46)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
at org.jboss.aspects.security.SecurityClientInterceptor.invoke(SecurityClientInterceptor.java:40)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:77)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:102)
... 2 more
Caused by: java.io.NotSerializableException: com.lyh.ejb3.domain.Customer
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeArray(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at java.rmi.MarshalledObject.<init>(Unknown Source)
at org.jboss.aop.joinpoint.MethodInvocation.writeExternal(MethodInvocation.java:261)
at java.io.ObjectOutputStream.writeExternalData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at org.jboss.remoting.serialization.impl.java.JavaSerializationManager.sendObject(JavaSerializationManager.java:81)
at org.jboss.remoting.marshal.serializable.SerializableMarshaller.write(SerializableMarshaller.java:84)
at org.jboss.remoting.transport.socket.SocketClientInvoker.transport(SocketClientInvoker.java:273)
... 14 more
解决方法:implements Serializable 实现序列化

我的联系方式:
QQ:495585885
Email:liuyuhui_007@yahoo.com.cn
我的博客:http://hi.baidu.com/vsandjava
与大家共同学习交流!

下载地址:
http://hi.baidu.com/vsandjava/blog/item/c1f99a16c109e851f2de32b1.html
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics