You can subscribe to this list here.
| 2002 | Jan (2) | Feb (157) | Mar (111) | Apr (61) | May (68) | Jun (45) | Jul (101) | Aug (132) | Sep (148) | Oct (227) | Nov (141) | Dec (285) | 
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 | Jan (518) | Feb (462) | Mar (390) | Apr (488) | May (321) | Jun (336) | Jul (268) | Aug (374) | Sep (211) | Oct (246) | Nov (239) | Dec (173) | 
| 2004 | Jan (110) | Feb (131) | Mar (85) | Apr (120) | May (82) | Jun (101) | Jul (54) | Aug (65) | Sep (94) | Oct (51) | Nov (56) | Dec (168) | 
| 2005 | Jan (146) | Feb (98) | Mar (75) | Apr (118) | May (85) | Jun (75) | Jul (44) | Aug (94) | Sep (70) | Oct (84) | Nov (115) | Dec (52) | 
| 2006 | Jan (113) | Feb (83) | Mar (217) | Apr (158) | May (219) | Jun (218) | Jul (189) | Aug (39) | Sep (3) | Oct (7) | Nov (4) | Dec (2) | 
| 2007 | Jan | Feb (2) | Mar (7) | Apr (3) | May (3) | Jun (8) | Jul (1) | Aug (1) | Sep | Oct (4) | Nov (7) | Dec | 
| 2008 | Jan (1) | Feb (1) | Mar | Apr | May | Jun | Jul (2) | Aug (4) | Sep | Oct (2) | Nov (1) | Dec | 
| 2009 | Jan (6) | Feb | Mar (1) | Apr (2) | May (1) | Jun (1) | Jul (10) | Aug | Sep (1) | Oct (1) | Nov | Dec (3) | 
| 2010 | Jan | Feb (1) | Mar | Apr | May | Jun | Jul | Aug | Sep (2) | Oct | Nov | Dec | 
| 2012 | Jan (1) | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec | 
| 2015 | Jan | Feb | Mar | Apr | May | Jun (1) | Jul | Aug | Sep | Oct | Nov | Dec | 
| 
      
      
      From: Doug C. <de...@fl...> - 2002-02-06 18:41:22
      
     | 
| Wednesday, February 06, 2002, 3:28:06 AM, Gavin wrote:
>> Yes. I currently use Persistent in two ways.
>>
>> 1. When computing the inheritance graph. As classes are added to the
>> set to be analyzed, I construct this graph (well, actually a set of
>> trees since Java is single inheritance). The lack of a Peristent
>> interface tells me when to stop climbing superclass links to insure
>> that all requisite classes are included
> I take it you mean you stop climbing the tree looking for _classes_.
> Properties from superclasses _should_ be included....
Ah. I did misunderstand this. I assumed properties of non-Persistent
classes were transient. I will fix it.
<snip>
> Another suggestion:
> One possible hueristic that "solves" both problems is to see if something
> there looks like an ID property. If theres none, its a component or a
> non-persistent superclass. A command line switch could even set a list of
> property names the user uses for IDs.
> I kind of like this solution because it isolates as much possible
> dodgy guessfulness in one single rule that the user can understand and
> control, rather than having ten different rules that interact in wierd
> and unpredictable ways.
I like it, too, especially for climbing the superclass chain, since
there is exactly one ID at its root that they all share. So, the user
can specify a class and an ID property (and optionally a generator)
and this completely specifies (a path through) the tree.
If the user wants multiple subclasses from different paths in the same
table, a list of fringe subclasses could be specified with one ID
property. For example, using the notation X[Y,Z] where X is a direct
superclass of Y and Z, in A[B[C],D[E]] with A's ID specified...
listing classes     yields table
---------------     ------------
B                   A{B}
E                   A{D{E}}
C,D                 A{B{C},D}
I suppose it's possible to specify a different list of subclasses and
get another table with the same or different root class. For example,
for class E with D's ID, you'd get table D{E}.
Now, I believe the rule is one table per class.
So this combination is legal:    A{B} and D{E}
but this combination is illegal: A{B} and A{D{E}}.
Right=3F
The current implementation would yield A{B,D{E}} in either case. But
if we add the extra ID argument, separate A{B} and D{E} tables becomes
possible.
As far as using IDs for choosing between association and component, I
am not as happy, but at least it is something.
>> Currently the following must be true of a class before it is added as
>> a persistent [super]class:
>> the class
>> C1. is not Primitive
>> C2. is not an Array
>> C3. is not an Interface
>> C4. is not nested (an inner class), i.e., c.getDeclaringClass() =3D=3D n=
ull
>> C5. is not Abstract
>> C6. has a public default constructor (0 arguments)
>> C7. implements Persistent
> C3 I _guess_ is reasonable, though not essential.
I don't think Interfaces can have properties unless they're
implemented in the concrete class. The real purpose of this rule is to
prevent command line specified Interfaces from appearing in the table.
The code would never find an Interface in the superclass chain.
>  C5 I dont think is right.
OK, I can easily remove it. What happens if the user tries to
instantiate an abstract class, e.g., with a query=3F
> C6 is changed to: it has a default constructor of any visibility level.
OK. But perhaps a warning is in order (=3F) since private 0-arg
constructors usually signal non-instantiable classes.
From Java Lang Spec 2nd edition:
If the intent is simply to prevent instantiation of a class, the
proper way to express this is to declare a constructor (=A78.8.8) of no
arguments, make it private, never invoke it, and declare no other
constructors. A class of this form usually contains class methods and
variables. The class Math is an example of a class that cannot be
instantiated
>> Determining property roles is much more difficult. Currently I am
>> using the following heuristic
<snip>
> Nothing should default to Serializable. Its almost always a bad idea to
> store things in serialized form. (Unless they are, genuinely a stream
> of bytes. eg. a JPEG or something.)
Agreed. I was lazy (Serializable is easy to determine,
component-izable isn't). I will fix the code.
An administrative question for Gavin:
Currently the MappingByReflection is implemented in a single Class
with several nested classes. Before tackling the above changes I
should probably refactor the code into a few top level classes; this
will facilitate its use by the eventual GUI tool and make maintenence
easier, I think. Can I claim package cirrus.hibernate.tools.reflect or
would you prefer it somewhere else=3F
e
 | 
| 
      
      
      From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-06 14:22:21
      
     | 
| > Just an idea. A really cool one. | 
| 
      
      
      From: Paul S. <pau...@ne...> - 2002-02-06 13:47:10
      
     | 
| Gavin_King/Cirrus%CI...@ci... wrote: [snip] >>It is also impossible for MappingByReflection to see inside lists, >>maps, and sets. Because they must be declared by their basic >>collection interface, the reflection code has no clue what they >>contain. >> > > Yeah, they should be left simply as stubs for the user to fill in. > Thats cool, if this tool does 70% of the work (the tedious work), > it already takes away 90% of the pain :) Perhaps we could use a similar approach to Beans introspection here - guess based on what methods exist. In beans you have a convention for naming indexed properties, there might be a broad enough generalisation we could apply here ourselves for guessing what's in a collection. e.g. for a List attribute blah, you might expect to find methods like addBlah( Foo ), removeBlah( Foo ) etc. and guess that blah contains Foo instances. I don't know if this works in the wider world, but perhaps worth considering something similar. We generally used method names based on the underlying collection class, e.g. for a List there's add, remove, list. For maps it's put/get, etc. Just an idea. PaulS. | 
| 
      
      
      From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-06 12:30:48
      
     | 
| I've been trying to figure out how to get Xerces to resolve a relative link to the DTD when I load the XML document using ClassLoader.getResourceAsStream() The problem is we dont know the path to the XML, so Xerces just chokes on the relative link. I even tried all type of things like implementing EntityResolver but even that didnt even work. Anyone have any experience with this? Its actually quite an important problem. I already hate having to specify the install_dir property to get the tests etc running and that would only get worse in a bigger proj. What you really want is to be able to specify a map directory and have hibernate find mapping files for classes there. (By default it could be the classpath.) So com.illflow.Foo would have a map in /com/illflow/Foo.hbm.xml. This is consistent with how Java itself does things and also its scalable and good for source control. But we dont want to have to hardcode an absolute path to the dtd. Also, I would love to be able to package maps + classes together in a jar. Yeah, i know, you can use a url on your webserver but thats still less than ideal.... | 
| 
      
      
      From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-06 08:39:25
      
     | 
| > Yes. I currently use Persistent in two ways. > > 1. When computing the inheritance graph. As classes are added to the > set to be analyzed, I construct this graph (well, actually a set of > trees since Java is single inheritance). The lack of a Peristent > interface tells me when to stop climbing superclass links to insure > that all requisite classes are included I take it you mean you stop climbing the tree looking for _classes_. Properties from superclasses _should_ be included.... I'm trying to think of a reason why _not_ to produce a mapping that includes non-persistent superclasses and the reason I can think of is because you want separate branches of the hierarchy to go in separate tables. I actually hadn't thought of this earlier... > 2. When determining the role of a property which is a reference to an > object. If the object's class implements Persistent, then it's an > association. Otherwise it's something else. Details below. This is the problem I _had_ thought of. How do we pick between a component and an entity class? > Currently it is only necessary to provide MappingByReflection the > fringe of the inheritance graph. We could insist that all classes to > be analyzed are provided, but this could lead to errors (missing > superclasses; holes in the graph -> extra tables which are too > sparse). I'm not against this solution. The things which look like problems could also be interpreted as "features" which give the user extra control. Asking the user to explicitly list all classes is actually less intrusive and logically equivalent to asking them to implement Persistent (well, excepting the possiblity for errors you raise). Another suggestion: One possible hueristic that "solves" both problems is to see if something there looks like an ID property. If theres none, its a component or a non-persistent superclass. A command line switch could even set a list of property names the user uses for IDs. I kind of like this solution because it isolates as much possible dodgy guessfulness in one single rule that the user can understand and control, rather than having ten different rules that interact in wierd and unpredictable ways. > Currently the following must be true of a class before it is added as > a persistent [super]class: > the class > C1. is not Primitive > C2. is not an Array > C3. is not an Interface > C4. is not nested (an inner class), i.e., c.getDeclaringClass() == null > C5. is not Abstract > C6. has a public default constructor (0 arguments) > C7. implements Persistent C3 I _guess_ is reasonable, though not essential. C5 I dont think is right. Hibernate itself doesnt care about the actual inheritence heirarchy and whether classes are instantiable. You could have an abstract class somewhere in the heirarchy of persistent classes. This is particularly important if we have Foo and Bar, both concrete classes, subclassing Baz, an abstract class, but we want to load foos and bars polymorphically from the database. Actually, the more I think about it, the more I think C3 should be dropped.... C6 is changed to: it has a default constructor of any visibility level. > What can we replace #7 with to limit the search? One possibility is > the class must be in the same toplevel package. E.g., system classes > would never be persistent. Opinions? Suggestions? hmmmm same toplevel package I hadn't thought of. Still not enough though, since we could still end up with everybody in the same table. Whatever we do we need to give the user _some_ way of indicating which classes go in the same table. > > Determining property roles is much more difficult. Currently I am > using the following heuristic, some of which is based on the logic in > Hibernate.auto... > > 1. Hibernate.basic(cls) != null => BASIC_KIND > 2. cls.isArray() => ARRAY_KIND > 3. Type.class.isAssignableFrom(cls) => CUSTOM_KIND; > 4. Persistent.class.isAssignableFrom(cls) => ASSOCIATION_KIND > 5. PersistentEnum.class.isAssignableFrom(cls) => ENUM_KIND > 6. java.util.List.class.isAssignableFrom(cls) => LIST_KIND > 7. java.util.Map.class.isAssignableFrom(cls) => MAP_KIND > 8. java.util.Set.class.isAssignableFrom(cls) => SET_KIND > 9. Serializable.class.isAssignableFrom(cls) => SERIALIZABLE_KIND > 10. else if C1..C6 above are true => COMPONENT_KIND > 11. else UNKNOWN_KIND (error) > > As Gavin points out, without Persistent, it is impossible to > distinguish ASSOCIATION_KIND from COMPONENT_KIND. > > But, the above heuristic has other problems. It cannot distinguish > SERIALIZABLE_KIND and COMPONENT_KIND -- the choice is arbitrary if > both modes are possible. It also cannot determine if collections and > arrays should be keyed (top level) or unkeyed. Nothing should default to Serializable. Its almost always a bad idea to store things in serialized form. (Unless they are, genuinely a stream of bytes. eg. a JPEG or something.) > It is also impossible for MappingByReflection to see inside lists, > maps, and sets. Because they must be declared by their basic > collection interface, the reflection code has no clue what they > contain. Yeah, they should be left simply as stubs for the user to fill in. Thats cool, if this tool does 70% of the work (the tedious work), it already takes away 90% of the pain :) > I plan to continue working on the MappingByReflection code in the hope > that someone will step forward to implement a GUI front end where some > of this missing information can be interactively supplied. Eventually we will need this. > As a snapshot of its current status, MappingByReflection produces the > XML output below given the args[]... > That looked brilliant! (Unfortunately some will have to change with the new hibernate-mapping DTD) | 
| 
      
      
      From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-06 07:11:20
      
     | 
| Yes, for sure java.sql.Time and friends should be understood by Hibernate.basic(). In fact I think that was always intended, they just never made it into code. I have added that. Also I am adding a TimeType to do bare time values. That will mean additions to all the Dialects >:| | 
| 
      
      
      From: Doug C. <de...@fl...> - 2002-02-06 06:44:46
      
     | 
| From the tutorial section on properties... >In certain cases you will still need the |type| attribute. (For >example, to distinguish between |Hibernate.DATE| and >|Hibernate.TIMESTAMP|, or to specify a custom type.) While working on reflection I wondered about permitting the option of using thin wrappers like java.sql.Date java.sql.Time and java.sql.Timestamp to make this more flexible. e | 
| 
      
      
      From: Doug C. <de...@fl...> - 2002-02-06 06:29:01
      
     | 
| Thank you Gabe Hicks for cirrus.hibernate.sql.Mckoi. You may want to change the comment there from /** Represents an SQL dialect compatible with Postgres */ to /** Represents an SQL dialect compatible with Mckoi */ I also added this in the example and test properties files... #Mckoi #hibernate.dialect cirrus.hibernate.sql.MckoiDialect #hibernate.driver com.mckoi.JDBCDriver #hibernate.url jdbc:mckoi:local://d:/db/db.conf #hibernate.username admin #hibernate.password ????? e | 
| 
      
      
      From: Doug C. <de...@fl...> - 2002-02-06 05:06:07
      
     | 
| Tuesday, February 05, 2002, 10:23:19 PM, Gavin wrote:
> Doug Currie, who was working on the reflective map generator will be
> affected most affected by the new mapping style and by deprecation of
> Persistent. Presumably some user input is no required in order to determine
> what classes are entities, which are components, which are to be
> serialized.
Yes. I currently use Persistent in two ways.
1. When computing the inheritance graph. As classes are added to the
set to be analyzed, I construct this graph (well, actually a set of
trees since Java is single inheritance). The lack of a Peristent
interface tells me when to stop climbing superclass links to insure
that all requisite classes are included.
2. When determining the role of a property which is a reference to an
object. If the object's class implements Persistent, then it's an
association. Otherwise it's something else. Details below.
Workarounds are possible for each of these, but they're not nice.
Currently it is only necessary to provide MappingByReflection the
fringe of the inheritance graph. We could insist that all classes to
be analyzed are provided, but this could lead to errors (missing
superclasses; holes in the graph -> extra tables which are too
sparse).
Currently the following must be true of a class before it is added as
a persistent [super]class:
the class
C1. is not Primitive
C2. is not an Array
C3. is not an Interface
C4. is not nested (an inner class), i.e., c.getDeclaringClass() == null
C5. is not Abstract
C6. has a public default constructor (0 arguments)
C7. implements Persistent
What can we replace #7 with to limit the search? One possibility is
the class must be in the same toplevel package. E.g., system classes
would never be persistent. Opinions? Suggestions?
Determining property roles is much more difficult. Currently I am
using the following heuristic, some of which is based on the logic in
Hibernate.auto...
1. Hibernate.basic(cls) != null           => BASIC_KIND
2. cls.isArray()                          => ARRAY_KIND
3. Type.class.isAssignableFrom(cls)       => CUSTOM_KIND;
4. Persistent.class.isAssignableFrom(cls) => ASSOCIATION_KIND
5. PersistentEnum.class.isAssignableFrom(cls) => ENUM_KIND
6. java.util.List.class.isAssignableFrom(cls) => LIST_KIND
7. java.util.Map.class.isAssignableFrom(cls)  => MAP_KIND
8. java.util.Set.class.isAssignableFrom(cls)  => SET_KIND
9. Serializable.class.isAssignableFrom(cls) => SERIALIZABLE_KIND
10. else if C1..C6 above are true => COMPONENT_KIND
11. else UNKNOWN_KIND (error)
As Gavin points out, without Persistent, it is impossible to
distinguish ASSOCIATION_KIND from COMPONENT_KIND.
But, the above heuristic has other problems. It cannot distinguish
SERIALIZABLE_KIND and COMPONENT_KIND -- the choice is arbitrary if
both modes are possible. It also cannot determine if collections and
arrays should be keyed (top level) or unkeyed.
It is also impossible for MappingByReflection to see inside lists,
maps, and sets. Because they must be declared by their basic
collection interface, the reflection code has no clue what they
contain.
So, my conclusion is that using the Hibernate style of persistence,
reflection will give us only very limited information. Removing
Persistent will hurt, but it is only one of many issues.
I plan to continue working on the MappingByReflection code in the hope
that someone will step forward to implement a GUI front end where some
of this missing information can be interactively supplied.
As a snapshot of its current status, MappingByReflection produces the
XML output below given the args[]...
cirrus.hibernate.test.Qux
cirrus.hibernate.test.Foo
cirrus.hibernate.test.Foo$Struct
cirrus.hibernate.test.Bar
cirrus.hibernate.test.Baz
cirrus.hibernate.test.Qux
Note that I have implemented a heuristic to find the UID property,
another shortcoming of reflection. I think everthing except nested
arrays and top level collections is basically working. I do need to:
check for duplicate table and column names and repair them, and add a
length to String and Binary columns.
e
-=-
<!-- Class cirrus.hibernate.test.Foo$Struct isn't Persistent! -->
<!-- cirrus.hibernate.test.Qux already added -->
<hibernate-mapping>
<!-- cirrus.hibernate.test.Qux root -->
 <class name="cirrus.hibernate.test.Qux" table="Qux" select="distinct">
    <id name="key" type="long" column="key">
      <generator class="hilo.long"/>
    </id>
    <property name="deleted" column="deleted" type="boolean"/>
    <property name="stuff" column="stuff" type="java.lang.String"/>
    <property name="created" column="created" type="boolean"/>
    <property name="loaded" column="loaded" type="boolean"/>
    <property name="stored" column="stored" type="boolean"/>
    <!-- association name="foo" type="cirrus.hibernate.test.Foo" -->
    <property name="foo" column="foo" type="cirrus.hibernate.test.Foo"/>
    <set role="fums" table="fums">
      <key column="uid"/>
      <element column="elm" type ="java.lang.String"/>
    </set>
    <list role="moreFums" table="moreFums">
      <key column="uid"/>
      <index column="i"/>
      <element column="elm/>
    </list>
 </class>
<!-- cirrus.hibernate.test.Foo root -->
 <class name="cirrus.hibernate.test.Foo" table="Foo" select="distinct" discriminator="subclass">
    <id name="key" type="java.lang.String">
      <column name="key" length="16"/>
      <generator class="hilo.hex"/>
    </id>
    <property name="binary" column="binary" type="[B"/>
    <property name="string" column="string" type="java.lang.String"/>
    <!-- array of basic name="custom" type="java.lang.String" -->
    <array role="custom" table="custom">
      <key column="uid"/>
      <index column="idx"/>
      <element column="elm" type ="java.lang.String"/>
    </array>
    <property name="blob" column="blob" type="java.io.Serializable"/>
    <property name="int" column="int" type="int"/>
    <property name="timestamp" column="timestamp" type="java.util.Date"/>
    <property name="short" column="short" type="java.lang.Short"/>
    <property name="yesno" column="yesno" type="boolean"/>
<!-- cirrus.hibernate.test.FooComponent -->
   <component name="component" class="cirrus.hibernate.test.FooComponent">
<!-- cirrus.hibernate.test.FooComponent -->
   <component name="subcomponent" class="cirrus.hibernate.test.FooComponent">
<!-- cirrus.hibernate.test.FooComponent -->
   <component name="subcomponent" class="cirrus.hibernate.test.FooComponent">
    <!-- component too deeply nested name="subcomponent" type="cirrus.hibernate.test.FooComponent" -->
    <property name="name" column="name" type="java.lang.String"/>
    <property name="count" column="count" type="int"/>
    <!-- array of basic name="importantDates" type="java.util.Date" -->
    <array role="importantDates" table="importantDates">
      <key column="uid"/>
      <index column="idx"/>
      <element column="elm" type ="java.util.Date"/>
    </array>
   </component>
    <property name="name" column="name" type="java.lang.String"/>
    <property name="count" column="count" type="int"/>
    <!-- array of basic name="importantDates" type="java.util.Date" -->
    <array role="importantDates" table="importantDates">
      <key column="uid"/>
      <index column="idx"/>
      <element column="elm" type ="java.util.Date"/>
    </array>
   </component>
    <property name="name" column="name" type="java.lang.String"/>
    <property name="count" column="count" type="int"/>
    <!-- array of basic name="importantDates" type="java.util.Date" -->
    <array role="importantDates" table="importantDates">
      <key column="uid"/>
      <index column="idx"/>
      <element column="elm" type ="java.util.Date"/>
    </array>
   </component>
    <property name="zero" column="zero" type="float"/>
    <property name="bool" column="bool" type="boolean"/>
    <property name="nullBlob" column="nullBlob" type="java.io.Serializable"/>
    <property name="null" column="null" type="java.lang.Integer"/>
    <property name="bytes" column="bytes" type="[B"/>
    <!-- enum name="status" type="cirrus.hibernate.test.FooStatus" -->
    <property name="status" column="status" type="cirrus.hibernate.test.FooStatus"/>
    <property name="long" column="long" type="java.lang.Long"/>
    <property name="integer" column="integer" type="java.lang.Integer"/>
    <!-- association name="foo" type="cirrus.hibernate.test.Foo" -->
    <property name="foo" column="foo" type="cirrus.hibernate.test.Foo"/>
    <property name="byte" column="byte" type="java.lang.Byte"/>
    <property name="boolean" column="boolean" type="java.lang.Boolean"/>
    <property name="date" column="date" type="java.util.Date"/>
    <property name="double" column="double" type="java.lang.Double"/>
    <property name="float" column="float" type="java.lang.Float"/>
<!-- cirrus.hibernate.test.Bar -->
 <subclass name="cirrus.hibernate.test.Bar">
    <property name="barString" column="barString" type="java.lang.String"/>
<!-- cirrus.hibernate.test.FooComponent -->
   <component name="barComponent" class="cirrus.hibernate.test.FooComponent">
<!-- cirrus.hibernate.test.FooComponent -->
   <component name="subcomponent" class="cirrus.hibernate.test.FooComponent">
<!-- cirrus.hibernate.test.FooComponent -->
   <component name="subcomponent" class="cirrus.hibernate.test.FooComponent">
    <!-- component too deeply nested name="subcomponent" type="cirrus.hibernate.test.FooComponent" -->
    <property name="name" column="name" type="java.lang.String"/>
    <property name="count" column="count" type="int"/>
    <!-- array of basic name="importantDates" type="java.util.Date" -->
    <array role="importantDates" table="importantDates">
      <key column="uid"/>
      <index column="idx"/>
      <element column="elm" type ="java.util.Date"/>
    </array>
   </component>
    <property name="name" column="name" type="java.lang.String"/>
    <property name="count" column="count" type="int"/>
    <!-- array of basic name="importantDates" type="java.util.Date" -->
    <array role="importantDates" table="importantDates">
      <key column="uid"/>
      <index column="idx"/>
      <element column="elm" type ="java.util.Date"/>
    </array>
   </component>
    <property name="name" column="name" type="java.lang.String"/>
    <property name="count" column="count" type="int"/>
    <!-- array of basic name="importantDates" type="java.util.Date" -->
    <array role="importantDates" table="importantDates">
      <key column="uid"/>
      <index column="idx"/>
      <element column="elm" type ="java.util.Date"/>
    </array>
   </component>
  </subclass>
 </class>
</hibernate-mapping>
 | 
| 
      
      
      From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-06 03:35:15
      
     | 
| Hi everyone :) (Very-nearly) all features of 0.9.4 are now working in the main project branch in CVS. Everyone should start using that branch as a baseline for new development. (Future breakages will be done in a new branch.) There have been a number of important changes: 1. As requested by Paul Szego, constructors may now be of any visibility. previously they were forced to be private 2. Also as requested by Paul, property naming now complies with JavaBeans specification ( "foo" instead of "Foo" ). Actually both styles now work. 3. Schema Generation now done by the map package (more OO) and there is a new command-line tool for exporting schema (cirrus.hibernate.test.DBSchemaExport). ALTER TABLE is no longer used to create tables and its now possible to drop tables with circular foreign key constraints on all databases. 3. The XML mapping has been changed in anticipation of us deprecating Persistent. The old style is deprecated but still works for classes that _do_ implement Persisent. Immediate priorities for me + Daniel are: 1. Deprecate the Persistent interface 2. Document new mapping style and the schema export tool Who is affected by this? Doug Currie, who was working on the reflective map generator will be affected most affected by the new mapping style and by deprecation of Persistent. Presumably some user input is no required in order to determine what classes are entities, which are components, which are to be serialized. Anyone like Phillip Baird who is working with databases with no ALTER TABLE statement will now be able to use hibernate for schema generation and properly test dialects. We can now start work on XML databinding (yay!) Also, would people please review the changes to hibernate-mapping.dtd and suggest futher changes (to naming or structure). We are thinking of releasing a version 0.9.5 on thursday or friday evening if no-one finds any issues or bugs with the current version. Thanks to everyone for their input so far! Peace Gavin | 
| 
      
      
      From: Paul S. <pau...@ne...> - 2002-02-06 02:26:36
      
     | 
| Paul Szego wrote: > > > In response to the "Lazy Initialization of Objects" request, some comments: > > Not trivial. Approaches that I know of: > - pre/post processing to insert code that manages this > - use of interfaces and proxies > - provide an API and let the coder do it. And I of course forgot one: - explicitly using some indirection object, a'la TOPLink ValueHolder's. In this case you declare your attribute to be an instance of a ValueHolder class, which has a dereference type method like "load" or whatever. PaulS :) | 
| 
      
      
      From: Phillip B. <phi...@cl...> - 2002-02-06 00:40:53
      
     | 
| Hi there, Just started taking a look at Hibernate 0.9.4 last night and thought I'd give it a go with HSQLDB (1.6.1). I've knocked up a dialect which seems to work ok with the the demo app if using a standalone database. HSQLDB is throwing an execption when I use the in-memory database option, but I've ignored that for the moment. Also the unit testing in FooBarTest fails. This looks to be because of ScriptGenerator rather than the actual persistence side of things. ScriptGenerator is using ALTER TABLE which HSQLDB does not appear to support in it's syntax. As it's pretty small I've attached the dialect if anyone is interested. regards Phillip B. | 
| 
      
      
      From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-04 13:30:15
      
     | 
| sorry... reading your email again I realise your point is more that things
like
foo.getClass().isAssignableFrom( bar.getClass() )
and
foo.getClass().isInstance(bar)
wont work ( where Bar inherits Foo ) but note that bar instanceof Foo still
works which is way more important.
I missed the little prime (') ....
Still I think if you are doing things like the above in your business model
code, you are probably doing something wrong. Such things should be rare
and where they _are_ used you can always just not use lazy init. I guess
theres still a worry about other tools that use reflection ......
Obviously bytecode processing is a more powerful technique for this
particular problem but also a *much* more difficult one to get right
(anyone wanna debug that stuff? Or read stack traces?)
Arguably, lazy instantiation of direct references is *much* less important
than lazy instantiation of collections anyway, so I wouldn't want to expend
too much effort upon this problem.
Gavin
 | 
| 
      
      
      From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-04 10:42:34
      
     | 
| 
Actually instanceof will still work. For example:
class Foo implements Persistent {
  String name;
  String id;
  String getName() {..}
  void setName(String name) { ...}
  String getID() { ....}
  void setID(String id) { .... }
  ......
}
Foo has the proxy subclass FooProx (not strictly a proxy cos its not really
using delegation)
FooProx extends Foo {
  String getName() { ....; return super.getName(); }
  void setName(String name) { ...; super.setName(name) }
  String getID() { ....; return super.getID(); }
  void setID(String id) { ....; super.setID(id); }
}
so an instance of FooProx is also an instance of Foo. So instanceof works
fine. also Foo.class.isAssignableFrom( foo.getClass() ) works.
foo.getClass().isAssignableFrom( Foo.class ) breaks but i think thats the
less important case. Actually def less important.
reflection still works .... you will get a different bunch of methods but
they do the right thing.....
foo.getClass()==Foo.class breaks ... thats kind of nasty ... could break
equals(). But then the proxies might even be smart enough to do something
special in the case of equals.
foo.getClass.getName() breaks...
notify(), wait() and synchronized() all work (they wouldnt if you were
using seperate wrapper objects.
most importantly == works which it wouldn't if you use seperate wrapper
objects that delegate.
Actually the reason all this is okay is because we are using polymorphism
which is fundamentally OO. So basically the only real problem is getClass()
and that only because its declared final on Object.
 | 
| 
      
      
      From: Paul S. <pau...@ne...> - 2002-02-04 10:00:13
      
     | 
| Gavin_King/Cirrus%CI...@ci... wrote: > > My preferred technique is this: > 1. Let the developer build the system without lazy instantiation > 2. At deployment time have a tool to generate proxy classes that inherit > the business classes and override every public, package and protected > method with a method that calls the initialization code when needed (and > then invokes super). This implies source generation which is quite easy to > do using reflection. > 3. At runtime, the persistence layer can check for the existence of a proxy > class (using a naming convention), if it exists, return that to the > application, otherwise return an initialized instance. > > This has following advantages: > 1. The only model intrusion is you cant use final classes or methods if you > want lazy initialization. That fine; you can still have one or the other on > a class by class basis. > 2. No code-generation required during the test/debug cycle. > 3. You can choose which classes are initialized lazily at deployment time, > simply by choosing which proxies to deploy. > 4. No mutilation of sourcecode - so line-numbers, etc stay intact in > stacktraces. > 5. No extra proxy objects floating around wasting memory. > 6. No use of reflection _inside_ the application code. (A reflective > solution here could actually be a performance hurdle if proxies get invoked > inside a loop.) > > Does anyone see any major disadvantages of this solution? The derived class worries me a little - I don't think that messing with the class hierarchy is that nice. In fact I think it's pretty dangerous. For example, given B inherits from A where both are persistent (non-abstract). If we create an A' this is no longer an ancestor of B. I can think of lots of other cases that wouldn't work so well either, e.g. instanceof, isAssiganbleFrom() for starters. Not being final bothers me slightly, but not as much as messing with the class hierarchy. The only post-processor I've seen work actually mangled the bytecode, inserting the necessary code into relevant methods (usually get/set methods). Regards, PaulS :) | 
| 
      
      
      From: Doug C. <de...@fl...> - 2002-02-04 09:50:23
      
     | 
| I am making progress on a MappingByReflection class.
Given the list of classes:
cirrus.hibernate.test.Qux
cirrus.hibernate.test.Foo
cirrus.hibernate.test.Foo$Struct
cirrus.hibernate.test.Bar
cirrus.hibernate.test.Baz
cirrus.hibernate.test.Qux
it makes the XML below.
I am pleased that subclassing is working, and that I am
finding the properties. I use interface Persistent to
determine when to stop climing the superclass chain.
The next step is to do something more sensible with the
type info, and separate out arrays and components.
I'm afraid the only way to find the id is through naming
heuristics. I'm open to suggestions.
e
/*
<!-- Class cirrus.hibernate.test.Foo$Struct isn't Persistent! -->
<!-- cirrus.hibernate.test.Qux already added -->
<hibernate-mapping>
<!-- cirrus.hibernate.test.Qux root -->
  <class name="cirrus.hibernate.test.Qux" table="Qux" select="distinct">
    <property name="foo" type="class cirrus.hibernate.test.Foo">
    <property name="created" type="boolean">
    <property name="deleted" type="boolean">
    <property name="loaded" type="boolean">
    <property name="stored" type="boolean">
    <property name="key" type="long">
    <property name="stuff" type="class java.lang.String">
    <property name="fums" type="interface java.util.Set">
    <property name="moreFums" type="interface java.util.List">
  </class>
<!-- cirrus.hibernate.test.Foo root -->
  <class name="cirrus.hibernate.test.Foo" table="Foo" select="distinct">
    <property name="foo" type="class cirrus.hibernate.test.Foo">
    <property name="key" type="class java.lang.String">
    <property name="string" type="class java.lang.String">
    <property name="date" type="class java.util.Date">
    <property name="timestamp" type="class java.util.Date">
    <property name="integer" type="class java.lang.Integer">
    <property name="long" type="class java.lang.Long">
    <property name="short" type="class java.lang.Short">
    <property name="float" type="class java.lang.Float">
    <property name="double" type="class java.lang.Double">
    <property name="boolean" type="class java.lang.Boolean">
    <property name="bytes" type="class [B">
    <property name="zero" type="float">
    <property name="bool" type="boolean">
    <property name="int" type="int">
    <property name="null" type="class java.lang.Integer">
    <property name="byte" type="class java.lang.Byte">
    <property name="yesno" type="boolean">
    <property name="blob" type="interface java.io.Serializable">
    <property name="nullBlob" type="interface java.io.Serializable">
    <property name="status" type="class cirrus.hibernate.test.FooStatus">
    <property name="binary" type="class [B">
    <property name="custom" type="class [Ljava.lang.String;">
    <property name="component" type="class cirrus.hibernate.test.FooComponent">
<!-- cirrus.hibernate.test.Bar -->
  <subclass name="cirrus.hibernate.test.Bar" table="Bar" select="distinct">
    <property name="barString" type="class java.lang.String">
    <property name="barComponent" type="class cirrus.hibernate.test.FooComponent">
  </subclass>
  </class>
<!-- cirrus.hibernate.test.Baz root -->
  <class name="cirrus.hibernate.test.Baz" table="Baz" select="distinct">
    <property name="stringSet" type="interface java.util.Set">
    <property name="stringDateMap" type="interface java.util.Map">
    <property name="stringList" type="interface java.util.List">
    <property name="intArray" type="class [I">
    <property name="fooArray" type="class [Lcirrus.hibernate.test.Foo;">
    <property name="stringArray" type="class [Ljava.lang.String;">
    <property name="setArray" type="class [Ljava.util.Set;">
    <property name="stringArrayMap" type="interface java.util.Map">
    <property name="setList" type="interface java.util.List">
    <property name="code" type="class java.lang.String">
    <property name="customs" type="interface java.util.List">
    <property name="fooSet" type="interface java.util.Set">
    <property name="components" type="class [Lcirrus.hibernate.test.FooComponent;">
  </class>
</hibernate-mapping>
*/      
 | 
| 
      
      
      From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-04 08:45:50
      
     | 
| I will integrate your code changes now. they seem slightly better than what i had in mind. Thanks. | 
| 
      
      
      From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-04 06:41:14
      
     | 
| >In response to the "Lazy Initialization of Objects" request, some comments: >Not trivial. Approaches that I know of: >- pre/post processing to insert code that manages this >- use of interfaces and proxies >- provide an API and let the coder do it. Unfortunately, there is no way to do this in Java that is extremely compatible with the philosophy of Hibernate (ie. use dynamic techniques as much as possible but minimize model intrusion) There are straightformard approaches in more dynamic languages like SmallTalk, Python et al. If Java would have let you create a java.lang.Proxy from a class, instead of only from interfaces, it would be much easier. My preferred technique is this: 1. Let the developer build the system without lazy instantiation 2. At deployment time have a tool to generate proxy classes that inherit the business classes and override every public, package and protected method with a method that calls the initialization code when needed (and then invokes super). This implies source generation which is quite easy to do using reflection. 3. At runtime, the persistence layer can check for the existence of a proxy class (using a naming convention), if it exists, return that to the application, otherwise return an initialized instance. This has following advantages: 1. The only model intrusion is you cant use final classes or methods if you want lazy initialization. That fine; you can still have one or the other on a class by class basis. 2. No code-generation required during the test/debug cycle. 3. You can choose which classes are initialized lazily at deployment time, simply by choosing which proxies to deploy. 4. No mutilation of sourcecode - so line-numbers, etc stay intact in stacktraces. 5. No extra proxy objects floating around wasting memory. 6. No use of reflection _inside_ the application code. (A reflective solution here could actually be a performance hurdle if proxies get invoked inside a loop.) Does anyone see any major disadvantages of this solution? | 
| 
      
      
      From: Paul S. <pau...@ne...> - 2002-02-04 06:03:49
      
     | 
| Daniel Bradby wrote: > We've had some good response to the latest publicity and are getting > some great requests for features. I've added them to the feature request > > part of the sourceforge project and would like ppl to feel free to > comment on them if they feel the need. > > I think at this stage of the project that would be a good place for ppl > to let us know of things they need or can see needing improvement. It > would also be a good place to discuss how this could be done and maybe > even assign ppl to the task. Just so we are all thinking the same way. > > So go check it out and keep sending in more requests. > > Daniel I started typing this as a comment in the request forum, but decided it probably didn't really belong there. In response to the "Lazy Initialization of Objects" request, some comments: Not trivial. Approaches that I know of: - pre/post processing to insert code that manages this - use of interfaces and proxies - provide an API and let the coder do it. IMO the first approach is the toughest, but the only true "transparent" persistence from the programmers point of view. I'd choose post- over pre-processing given a choice (I've used both). The other two choices put some burden back on the developer, the third choice more so although it doesn't require polluting your model with otherwise unnecessary interfaces. But both fit in with the idea that "simple stuff is easy, and hard stuff is possible". I don't know that they'd be mutually exlcusive either, so you might choose to gradually introduce this. For example build the API first and test it. Then do the interface/proxy thing, which might use this API anyway. Then finally hack around with post-processing, which would use all the tricks you'd developed doing the other two. PaulS :) | 
| 
      
      
      From: Daniel B. <db...@bi...> - 2002-02-04 02:09:59
      
     | 
| We've had some good response to the latest publicity and are getting some great requests for features. I've added them to the feature request part of the sourceforge project and would like ppl to feel free to comment on them if they feel the need. I think at this stage of the project that would be a good place for ppl to let us know of things they need or can see needing improvement. It would also be a good place to discuss how this could be done and maybe even assign ppl to the task. Just so we are all thinking the same way. So go check it out and keep sending in more requests. Daniel | 
| 
      
      
      From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-04 01:45:55
      
     | 
| From the JavaBeans spec: >8.8 Capitalization of inferred names. >When we use design patterns to infer a property or event name, we need to decide what rules to follow for capitalizing the inferred name. If we extract the name from the middle of a normal mixedCase style Java name then the name will, by default, begin with a capital letter. >Java programmers are accustomed to having normal identifiers start with lower case letters. Vigorous reviewer input has convinced us that we should follow this same conventional rule for property and event names. >JavaBeans Introspection >Thus when we extract a property or event name from the middle of an existing Java name, we normally convert the first character to lower case. However to support the occasional use of all upper-case names, we check if the first two characters of the name are both upper case and if so leave it alone. So for example, >FooBah becomes fooBah >Z becomes z >URL becomes URL >We provide a method Introspector.decapitalize which implements this conversion rule. They actually contradict themselves earlier in the document with this: >Properties may be exposed in scripting environments as though they were fields of objects. So in a Javascript environment I might do ?b.Label = foo? to set the value of a property. But I think its clear that Paul is right and we need to support the lowercase style. Daniels just entering that as a feature request now.... (I would like to stay backward compatible though ... we should accept both FooBar and fooBar.) | 
| 
      
      
      From: Gavin_King/Cirrus%<CI...@ci...> - 2002-02-04 01:02:01
      
     | 
| Everyone please note that schema generation in the HEAD branch is (intentionaly) very broken currently. I will be able to get it working again in a couple of days (but using entirely different code). The STABLE branch contains functional schema generation. I guess I did wrong by checking the map refactorings into the HEAD branch instead of into a new UNSTABLE branch ... i wont do that again. Sorry about about that. | 
| 
      
      
      From: Doug C. <de...@fl...> - 2002-02-03 20:59:23
      
     | 
| Gavin wrote > The other tool I'd love to see is a GUI that lets the user map classes and > properties of classes (discovered by relection) to database tables and > columns _visually_ and spits out XML mappings. A first step towards this > would be a simple commandline tool that generates a skeleton mapping given > the name of a class. Perhaps a more general approach would be a tool that stored mappings into the Datastore by reflection, and a second tool that dumps (portions of) the Datastore in XML format, sorta the way generateSchema dumps in SQL format. Then the gui tool would be a "Datastore editor" that could use the guts of the above commandline tool(s) to "import" from classes and "export" to XML files. [I am NOT a gui guy! But I may take a look at doing a mappings by reflection tool.] e | 
| 
      
      
      From: Doug C. <de...@fl...> - 2002-02-03 20:43:44
      
     | 
| I caught up with the HEAD stream today, and tried the
NetworkInteractive example to see if it generated the sql for table
creation. I found that it needed a System property for the driver,
which is different from the old behavior. To repair this I made
changes in cirrus.hibernate.Environment and
cirrus.hibernate.impl.RelationalDatastore.
In Environment I added a new version of dialect() and the cache code:
        private static Dialect dialectCache = null;
        
        public static Dialect dialect() throws HibernateException {
                if( dialectCache != null ) return dialectCache;
                try {
                        dialectCache = (Dialect) Class.forName( System.getProperty(DIALECT) ).newInstance();
                        return dialectCache;
                }
                catch (Exception e) {
                        throw new HibernateException("The dialect was not set, or did not exist");
                }
        }
        
        public static Dialect dialect(Properties connectionProps) throws HibernateException {
                if( dialectCache != null ) return dialectCache;
                try {
                        dialectCache = (Dialect) Class.forName( connectionProps.getProperty(DIALECT) ).newInstance();
                        return dialectCache;
                }
                catch (Exception e) {
                        return dialect();
                }
        }
        
In RelationalDatastore I modified two methods (including changing the
signature for generateSchema...
        public SessionFactory buildSessionFactory(Properties connectionProps) throws HibernateException {
                generateSchema(Environment.dialect(connectionProps));
                Query.clearCache(); //ByIDQuery.clearCache();
                return new RelationalDatabaseSessionFactory(this, connectionProps);
        }
        public void generateSchema(Dialect dialect) throws HibernateException {
                //Dialect dialect = Environment.dialect();
                ...
        }
Now I can run the NetworkInteractive example as before. It prints the
create statements for the tables. It would be nice if it also provided
the statements to create the necessary unique ID table(s).
e
 | 
| 
      
      
      From: Paul S. <pau...@ne...> - 2002-02-03 15:25:59
      
     | 
| Daniel Bradby wrote: >> >> On the negative side, it is an extra unnecessary intrusion upon the model >> so all things considered it was probably a bad idea. A couple of people >> already commented negatively about it. >> > It doesn't force you to actually implement anything AND thanks to being > able to implement multiple interfaces, it doesn't get in the road of any > business model. It's a pain for me, and I can think of a few reasons why it might be undesirable: * adding persistence to existing code (PITA factor) * polluting "business" classes with persistence details (purist whinge) I use a "solution neutral" data management "layer" that allows me to use different persistence solutions, e.g. TOPLink or Hibernate or whatever. Having visibility to hibernate classes (or TOPLink or whatever) isn't a great idea in this situation. I know it's not a huge deal, since the interface is empty, but if there's no *need* for it I'd personally like to remove it. Some approaches advocate using it so they can tell what should be persisted, e.g. for "persistence by reachability". But since we have the mapping spec to tell us that I don't see the need. > Sounds great Paul! I've always wanted to play with Doclets and I've > never actually seen anything useful done with them. I was thinking this > was a good way to keep information about the classes together, but then > I am thinking that this seperation is part of what Hibernate is about. > Seperating your clean/pure OO business model from the OO dirty > relational model ;) > > Either way. Great thing to be able to add to a feature list. Allowing > ppl to configure via handed coded XML, plain GUI, IDE plugins AND from > source parsing. Can anyone complain? I'll get the source in order and plonk it somewhere in the next couple of days. It's only basic (i.e. it does what I needed for now), but rather than try to guess what should be in a more complete version I'll show whats there and get some feedback. Regards, PaulS :) |