GWT + Hibernate 多对一 xml O/R 映射:SerializationException

GWT + Hibernate many-to-one xml O/R Mapping: SerializationException

我目前正在开发一个 GWT + Hibernate 项目,它应该在一个已经定义和填充的数据库上协同工作。我收到

com.google.gwt.user.client.rpc.SerializationException

当我查询数据库时。

这是我的对象...

数据库:

-- Table: asset
CREATE TABLE IF NOT EXISTS asset
(
isin VARCHAR(12) NOT NULL,
mic_code VARCHAR(4) NOT NULL DEFAULT 'n.a.',
name VARCHAR(255) NOT NULL,
type_id VARCHAR(36) NOT NULL,
PRIMARY KEY (isin, mic_code),
INDEX(isin, mic_code),
FOREIGN KEY (type_id) REFERENCES asset_type(id)
)ENGINE=InnoDB;

-- Table: asset_type
CREATE TABLE IF NOT EXISTS asset_type
(
id VARCHAR(36) NOT NULL,
type VARCHAR(40) NOT NULL,
PRIMARY KEY (id)
)ENGINE=InnoDB;

Asset.java:

public class Asset implements Serializable {

    private String isin;
    private String mic_code;
    private String name;
    private AssetType assetType;

    public Asset() {
        super();
    }
...

AssetType.java

public class AssetType implements Serializable {

    private String id;
    private String type;

    public AssetType() {
    }

最后是休眠 xml 文件: Asset.hbm.xml

<hibernate-mapping>
    <class name="com.mygwtproject.shared.model.Asset" table="ASSET">
        <id name="isin" type="java.lang.String" access="field">
            <column name="ISIN" />
            <generator class="native" />
        </id>
        <property name="mic_code" type="java.lang.String" access="field">
            <column name="MIC_CODE" />
        </property>
        <property name="name" type="java.lang.String" access="field">
            <column name="NAME" />
        </property>
        <many-to-one name="assetType" class="com.mygwtproject.shared.model.types.AssetType" column="TYPE_ID" cascade="all" not-null="true"/>
    </class>
</hibernate-mapping>

AssetType.hbm.xml

<hibernate-mapping>
    <class name="com.mygwtproject.shared.model.types.AssetType" table="ASSET_TYPE">
        <id name="id" type="java.lang.String" column="ID"> 
            <generator class="native" />
        </id>
        <property name="type" type="java.lang.String" column ="TYPE" />
    </class>
</hibernate-mapping>

hibernate.cfg.xml

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.password">*****</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost/asset_db</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.current_session_context_class">thread</property>
        <property name="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="use_sql_comments">true</property>

        <mapping resource="com/mygwtproject/shared/model/Asset.hbm.xml" />
        <mapping resource="com/mygwtproject/shared/model/types/AssetType.hbm.xml" />
    </session-factory>
</hibernate-configuration>

来自日志:

Hibernate: 
    select
        assettype0_.ID as ID1_1_0_,
        assettype0_.TYPE as TYPE2_1_0_ 
    from
        ASSET_TYPE assettype0_ 
    where
        assettype0_.ID=?
09:43:09,139 TRACE BasicBinder:81 - binding parameter [1] as [VARCHAR] - [ee5bb49a-dc95-403a-9f77-864a9c342f25]
09:43:09,142 TRACE BasicExtractor:78 - extracted value ([TYPE2_1_0_] : [VARCHAR]) - [Stock]
Starting Jetty on port 8888
   [WARN] Exception while dispatching incoming RPC call
com.google.gwt.user.client.rpc.SerializationException: Type 'com.mygwtproject.shared.model.types.AssetType_$$_jvst77c_0' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = com.mygwtproject.shared.model.types.AssetType@7d617ac9

所以我的 Asset -> AssetType 映射有问题,但我找不到它。任何帮助表示赞赏。谢谢

编辑:

mysql> select * from asset_type where id = 'ee5bb49a-dc95-403a-9f77-864a9c342f25';

returns

+--------------------------------------+-------+
| id                                   | type  |
+--------------------------------------+-------+
| ee5bb49a-dc95-403a-9f77-864a9c342f25 | Stock |
+--------------------------------------+-------+
1 row in set (0.00 sec)

来自here的解决方案:

1.创建对应的数据传输对象并替换休眠对象。

AssetDTO.java

public class AssetDTO implements Serializable {

    private String isin;
    private String mic_code;
    private String name;
    private AssetTypeDTO assetType;

    public AssetDTO() {
        super();
    }

    public AssetDTO(String isin, String mic_code, String name,
            AssetTypeDTO assetType) {
        super();
        this.isin = isin;
        this.mic_code = mic_code;
        this.name = name;
        this.assetType = assetType;
    }

//incl. Getter + Setter
}

AssetTypeDTO.java

public class AssetTypeDTO implements Serializable {

    private String id;
    private String type;

    public AssetTypeDTO() {
        super();
    }

    public AssetTypeDTO(String id, String type) {
        super();
        this.id = id;
        this.type = type;
    }

   //incl. Getter + Setter
}

2。向休眠对象添加一个新的构造函数。

Asset.java

...
public Asset(AssetDTO dto) {
        this.isin = dto.getIsin();
        this.mic_code = dto.getMic_code();
        this.name = dto.getName();
        AssetTypeDTO assetTypeDTO = dto.getAssetType();
        if (assetTypeDTO != null) {
            this.assetType = new AssetType(assetTypeDTO.getId(),
                    assetTypeDTO.getType());
        }
 }
...

AssetType.java

public AssetType(AssetTypeDTO dto) {
        this.id = dto.getId();
        this.type = dto.getType();
    }

3。修改您的 GWT RPC 组件。 替换

中的 Hibernate 对象

IService.java

public List<Asset> getAssets();

使用 DTO。

public List<AssetDTO> getAssets();

IServiceAsync.java

public void getAssets(AsyncCallback<List<Asset>> callback);

public void getAssets(AsyncCallback<List<AssetDTO>> callback);

4.修改您的服务实现。

ServiceImpl.java

...
@Override
public List<AssetDTO> getAssets() {
    ...
    Query q = session.createQuery("from Asset");
    List<Asset> assets = new ArrayList<Asset>(q.list());
    List<AssetDTO> assetsDto = new ArrayList<AssetDTO>();
    if (assets != null) {
        for (Asset asset : assets) {
            assetsDto.add(createAssetDTO(asset));
        }
    }
    session.getTransaction().commit();
    return assetsDto;
}

public AssetDTO createAssetDTO(Asset asset) {
    AssetTypeDTO assetTypeDto = new AssetTypeDTO(asset.getAssetType()
                .getId(), asset.getAssetType().getType());
    AssetDTO result = new AssetDTO(asset.getIsin(), asset.getMicCode(),
                asset.getName(), assetTypeDto);
    return result;
}
...

5.将 Hibernate 对象 (Asset, AssetType) 移动到 server 包,将 DTO (AssetDTO, AssetTypeDTO) 移动到 shared 包并更新 Hibernate 中的路径 xml 个文件。