20090423

来源:互联网 发布:java用户角色权限管理 编辑:程序博客网 时间:2024/06/04 17:59

去掉数据库表的所有外键约束,在hibernate中关联的时候不用主键来关联。

 

@Entity(name="menu")
@Table(name="T_MENUITEM")
public class MenuItem extends AdvanceRecordableEntity implements Serializable {
 @OneToMany(mappedBy="parentMenuItem", fetch=FetchType.LAZY)//
 public Set<MenuItem> getChildMenuItems() {
  return childMenuItems;
 }
 public void setChildMenuItems(Set<MenuItem> childMenuItems) {
  this.childMenuItems = childMenuItems;
 }
 
 @ManyToOne
    @JoinColumn(name="PARENT_MENU_ID", referencedColumnName="MENU_ID")//

 public MenuItem getParentMenuItem() {
  return parentMenuItem;
 }
 public void setParentMenuItem(MenuItem parentMenuItem) {
  this.parentMenuItem = parentMenuItem;
 }
}

 

这样,一个菜单项可以取得它的子菜单项,也可以得到它的父菜单项。按上面这种写法,如果referencedColumnName指定的是targetEntity的主键,那么完全没问题。但是,如果指定的不是主键而是某一列属性的话(就像上面这样,MENU_ID不是主键),直接运行会出问题,这个问题是由于Hibernate的log系统产生,老外有相关的报告:

Debug level logging attempted by MessageHelper falls over when constructing a loggable string for a mapped collection on the main entity.

Following the code in the stacktrace, I can see that MessageHelper expects the parent key for the collection relationship to be the primary key, but it is mapped to another field of a different type via a property-ref. Hence the ClassCastException below.

The work around is to set logging to INFO or higher.

I have also attached a pared-down zip with the maven 2 project containing the mappings and the unit test which fails.

The following JIRA issue may be the same thing:

http://opensource.atlassian.com/projects/hibernate/browse/ANN-298

The following messages on the Hib forum demonstrate other interest in this issue:

http://forum.hibernate.org/viewtopic.php?t=949913

http://forum.hibernate.org/viewtopic.php?t=956778

http://forum.hibernate.org/viewtopic.php?t=962471



java.lang.ClassCastException: com.nomadsoft.cortex.domain.country.basic.BasicCountry
at org.hibernate.type.StringType.toString(StringType.java:44)
at org.hibernate.type.NullableType.toLoggableString(NullableType.java:168)
at org.hibernate.pretty.MessageHelper.collectionInfoString(MessageHelper.java:284)
at org.hibernate.loader.Loader.readCollectionElement(Loader.java:972)
at org.hibernate.loader.Loader.readCollectionElements(Loader.java:635)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:580)
at org.hibernate.loader.Loader.doQuery(Loader.java:689)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1785)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:47)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:41)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:2730)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:365)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:346)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:123)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:177)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:87)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:862)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:799)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:792)
at org.springframework.orm.hibernate3.HibernateTemplate$1.doInHibernate(HibernateTemplate.java:452)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:366)
at org.springframework.orm.hibernate3.HibernateTemplate.get(HibernateTemplate.java:446)
at org.springframework.orm.hibernate3.HibernateTemplate.get(HibernateTemplate.java:440)
at com.nomadsoft.cortex.infrastructure.hibernate.HibernateCountryRepository.getById(HibernateCountryRepository.java:26)
at com.nomadsoft.cortex.domain.country.basic.BasicCountryService.getCountry(BasicCountryService.java:34)
        etc etc

 

所以将log4j.properties里,将hibernate的日志级别设到INFO便可以正常运行通过。

 

然后又出现了一个问题,在运行时 PersistableEntity 类中的下面这个方法会有一个空指针异常:

public int hashCode() {
        return getId().hashCode();
    }

排查后发现是getId()这个方法返回是null,原因还没有研究。加上判断的逻辑后成功运行。

public int hashCode() {
     if (getId() == null) {
      return super.hashCode();
     } else {
      return getId().hashCode();
     }
    }

 

是否有其他影响还不清楚

 

 

另外一点要注意,如果用了referencedColumnName这个属性,那这个属性所指的targetEneity一定要实现Serializable接口,不然会报错

 

 

 

*******************************************************************************

 

用blazeDS取得上面定义的MenuItem,如果取子菜单时,定义fetch=FetchType.EAGER则没有问题,但是如果定义成

fetch=FetchType.LAZY则会出现lazyIniatial的错误,原因不明

 

 

*******************************************************************************

IconUtility Component for Dynamic Run-Time Icons

I’ve seen a number of emails on the flexcoders mailing list and even a few blog posts that are asking a very specific question: “How do you use run-time loaded images as the icon for buttons, containers, and related components?”. The answer they’ve gotten so far is that you can’t, at least not without creating a lot of custom components. The icon styles built into the Flex framework were only intended for embedded graphics. Although internally they can work with almost any DisplayObject as the icon, the styles and properties themselves are typed as Class. So how can you turn a DisplayObject into a Class?

To be honest, I hit my head against the wall on this one for a handful of evenings. In the end I came up with two workable solutions. Arguably the cleanest way would be to take the run-time loaded graphics, dynamically generate the bytes for a swf which contains that image as a BitmapAsset, and then load the swf to retrieve the generated Class. This would allow you to assign an honest to goodness BitmapAsset Class to the icon property. The problem I had with this method is that it wouldn’t be very easy for developers to use. Even if I created a class to generate the swf from a Loader, there would be some ActionScript involved for the developer to wait for the swf to be loaded and assign the resulting class to the right place. After thinking it through, I decided not to implement this solution. Instead, I found a way to turn the original question on it’s head.

After stepping through the code that handles the icon assignment a few times, I realized the original question, “How can you turn a DisplayObject into a Class?” should really be phrased “How can you reference a Class which displays the right DisplayObject when instantiated?”. This is an easier problem to solve. For my first attempt, I’ve created the IconUtility class. It includes a static method which accepts a url and a component reference, then returns a reference to the IconUtility class itself (which happens to extend BitmapAsset). When the class is instantiated, it will use the information you have passed in to determine which image should be displayed. I’ve decided to release it through my blog for now, since it is still unpolished and a bit of a hack.

<mx:Button id="example" label="Example" icon="{IconUtility.getClass(example, 'http://www.exampledomain.com/image.jpg')}" />

 

但是在自己的程序里应用这个IconUtility时又产生了不少问题:

1.如何绑定到icon,经实验,如下可以成功

 <mx:HBox xmlns:mx=http://www.adobe.com/2006/mxml creationComplete="showIcon(event)">

 <mx:Script>
  <![CDATA[

    [Bindable]
   private var _icon:Class;

   [Bindable]
   private var _data:MenuItem;

 

   override public function set data(value:Object):void{
             if (value != null) {
              _data = value as MenuItem;
             }
   }

   override public function get data():Object{
                    return _data;
   }

   private function showIcon():void {

    trace(flash.utils.getTimer().toString()+" >> "+event.currentTarget.name+" "+event.type);
    if (_data != null && _data.menuIconUrl != null) {
     _icon = IconUtility.getClass(moduleMenu, _data.menuIconUrl);
    }
   }

]]>
 </mx:Script>
 <mx:LinkButton id="moduleMenu" icon="{_icon}" />

 

通过在showIcon方法里trace一下,可以发现showIcon方法被执行了两次:

6850 >> MenuItemView246 creationComplete
6860 >> hiddenItem creationComplete        ------这个hiddenItem是什么,还没研究     

 

如果继续在LinkButton上加creationComplete事件的话,输出如下:

7061 >> moduleMenu creationComplete
7062 >> MenuItemView246 creationComplete
7071 >> moduleMenu creationComplete
7072 >> hiddenItem creationComplete

奇怪的事情,有点不明白

     

2.

 

另,应用buttonlink这么复杂的icon,不如定义itemrenderer时直接设置成image组件加上linkbutton组件

 

 

 

******************************************************************************************

原创粉丝点击