All, Again -- many thanks to the posters and responders on this thread. i've moved on to attempt to use ScalaQuery<http://github.com/szeiger/scala-query/tree/master>as the target for the SQL persistence. Stefan Szeiger describes his work here<http://szeiger.de/blog/2008/12/21/a-type-safe-database-query-dsl-for-scala/#more-24> .
It seems to be a week of meeting resistance, however. i've been attempting to build the simplest possible collection to use as a toy to test my compilation strategy. This has turned out to be quite a little brain-teaser. For me simpler means: contains less information. In this sense, a Set is simpler than a List. The simplest possible collection i can imagine (that still supports associativity -- and i don't know if i can call something that doesn't support associativity a collection) is a monad. A monad doesn't commit to what the collection contains; only parametrically commits to how to put things into the collection; and only parametrically commits to how to flatten the collection (which is tantamount to supporting associativity). After thinking about it for half a day, and revisiting the Moors-Piessens-Odersky (MPO) paper on higher-kinded types, i realized that the MPO construction doesn't actually apply to Scala in practice (someone please tell me if i'm wrong) because they fundamentally rely on constructions using type *members* and not type *parameters*. Unfortunately, most of the collections libraries are written using type parameters. So, i decided to roll my own and see what i got. Here's what i came up with last night. // smallest expression of monad i can find trait MBrace[C[_] <: MBrace[C,A],A] { def nest( a : A ) : C[A] def flatten[T <: C[C[A]]]( bsq : T ) : C[A] } // one of the simplest witnesses of monad i can find class MBraceSeq[A]( a_ : A* ) extends Seq[A] with MBrace[MBraceSeq,A] { override def nest( a : A ) = new MBraceSeq[A]( a ) override def flatten[T <: MBraceSeq[MBraceSeq[A]]]( bsq : T ) : MBraceSeq[A] = { (new MBraceSeq[A]( ) /: bsq)( { ( acc : MBraceSeq[A], e : MBraceSeq[A] ) => ( acc ++ e ).asInstanceOf[MBraceSeq[A]] } ) } override def length = a_.length override def elements = a_.elements override def apply( n : Int ) = a_.apply( n ) } i was mostly ok with this -- apart from some desiderata/concerns regarding the Seq methods being visible at this level. i woke up this am and realized that this is not even wrong. It requires an instance of MBrace to invoke the nest or flatten methods. Geez, i feel like a first year undergrad. All i want to do is write the simplest possible collection on which i can then test a persistence strategry and i run into roadblocks everywhere. ;-) Best wishes, --greg On Wed, Jun 24, 2009 at 8:00 AM, Derek Chen-Becker <dchenbec...@gmail.com>wrote: > Well, in my real-world experience I've never had very complex models and > I've never used TABLE-PER-CLASS either, so I don't really have a feel for > what's not possible. Generally I think that JPA (which is a subset of > Hibernate) covers a good portion of people's needs for ORM, but it > definitely has some big missing functionality (e.g. no ordered collections > until JPA 2). I think that in this case Greg is pushing the limits on a > relatively unused corner of JPA (I've never seen someone use TABLE-PER-CLASS > before) and he's hitting some bugs. I want to make clear that I think that > what Greg is attempting is entirely possible. My earlier comment about > rolling your own ORM was because I misunderstood what he was doing with > abstract classes. In my mind, there would be a couple of places where you > might want to roll your own stuff: > > > 1. An existing schema that doesn't map well to an object graph. We have > a legacy database at work where the brilliant developers decided that > nothing should be normalized and data can exist in one of four tables based > on some arcane business logic. You can still build an ORM layer on > something > like this, but essentially all you're doing is creating a thin wrapper on > ResultSets > 2. You have very specific data that you need to retrieve with possibly > complex joins, and you need it to be as performant as possible. There are > some tricks you can do with EJB QL to make it prefetch things, but often > you > can end up with multiple round trips to the database and/or data that you > don't need being fetched. In certain scenarios I could see this being an > issue. > > This list isn't intended to be exhaustive, these are just the top two that > come to mind. In terms of Hibernate vs others like JPOX, TopLink, etc, I'd > say that Hibernate is a first-class provider and at least equal to the > others. > > Derek > > > On Wed, Jun 24, 2009 at 2:21 AM, TSP <tim.pig...@optrak.co.uk> wrote: > >> >> Derek >> Would you distinguish between what is achievable in a specific ORM >> such as Hibernate from JPA in this statement or would you think it >> applies to all. I've got to "go with hibernate" in any case because of >> widespread use of UserTypes. Unlike Greg, in my case I can hand-craft >> all my hibernate xml files if I need. >> >> Tim >> >> On Jun 23, 1:46 am, Derek Chen-Becker <dchenbec...@gmail.com> wrote: >> > For sufficiently complex relationships, JPA is not a good fit. Beyond a >> > certain point it's usually simpler to roll your own. I think that this >> is >> > somewhat of a failing of the model, but it's not a simple problem to >> solve >> > in the generic case. >> > >> > Derek >> > >> > On Mon, Jun 22, 2009 at 6:45 PM, Derek Chen-Becker < >> dchenbec...@gmail.com>wrote: >> > >> > >> > >> > > Ah, sorry, I lost track of the thread. >> > >> > > On Mon, Jun 22, 2009 at 4:55 PM, Meredith Gregory < >> > > lgreg.mered...@gmail.com> wrote: >> > >> > >> Derek, >> > >> > >> You are correct and i noted and reported this on Scala on Friday. >> However, >> > >> if you have a chain of the form >> > >> > >> AbstractClass <- Class <-contains- AbstractClass <-Class <-contains- >> ... >> > >> > >> The @MappedSuperclass solution fails at level 2. >> > >> > >> Best wishes, >> > >> > >> --greg >> > >> > >> On Mon, Jun 22, 2009 at 3:52 PM, Derek Chen-Becker < >> dchenbec...@gmail.com >> > >> > wrote: >> > >> > >>> Something I just want to throw out into the discussion: Since you're >> > >>> using table-per-class, having a @Table annotation on >> AbstractContainer >> > >>> doesn't do anything since abstract classes can't have instances. >> Tables are >> > >>> only generated for abstract classes if you're using a JOINED >> inheritance >> > >>> strategy. You might want to look at using the MappedSuperclass >> annotation >> > >>> for the abstract base class instead. If I change the >> AbstractContainer def >> > >>> to: >> > >> > >>> @MappedSuperclass >> > >>> public abstract class AbstractContainer implements >> java.io.Serializable { >> > >> > >>> and then modify MySampleFuContainer to: >> > >> > >>> public class MySampleFuContainer extends AbstractContainer { >> > >> > >>> then I seem to get the proper schema: >> > >> > >>> create table lingo_production.MySampleFuContainer_table ( >> > >>> id varchar(255) not null, >> > >>> uuid varchar(255), >> > >>> mysamplingmumble__idSuper varchar(255), >> > >>> primary key (id), >> > >>> unique (uuid) >> > >>> ); >> > >> > >>> Having said that, I think that the behavior you're currently seeing >> > >>> appears to be a bug. >> > >> > >>> Derek >> > >> > >>> On Mon, Jun 22, 2009 at 3:43 PM, Meredith Gregory < >> > >>> lgreg.mered...@gmail.com> wrote: >> > >> > >>>> Kris, >> > >> > >>>> Here< >> http://svn.biosimilarity.com/src/open/codesamples/trunk/hibernate/>is a >> link to the self-contained example that now uses just Java. i included >> > >>>> the target dir in the repo to speed up investigation, but you can >> just blow >> > >>>> that away and build from scratch. The example is currently written >> to >> > >>>> Java1.6, but also exhibits the same behavior under Java1.5. To run >> the >> > >>>> example >> > >> > >>>> > svn co >> > >>>>http://svn.biosimilarity.com/src/open/codesamples/trunk/hibernate >> > >>>> ... >> > >>>> > env PATH=<path-to-java1.6>:$PATH JAVA_HOME=<path-to-java1.6> mvn >> clean >> > >>>> compile process-classes >> > >> > >>>> If you switch comment and decl at line 22 in >> > >>>> src/main/java/maxb/hbex2/MySampleFuContainer.java then you see the >> error. >> > >>>> The schema goes from >> > >> > >>>> create table lingo_production.MySampleFuContainer_table ( >> > >>>> id_AbstractContainer varchar(255) not null, >> > >>>> varchar(255) not null, >> > >>>> uuid varchar(255), >> > >>>> mysamplingmumble__idSuper varchar(255), >> > >>>> primary key (id), >> > >>>> unique (uuid) >> > >>>> ); >> > >> > >>>> to >> > >> > >>>> create table lingo_production.MySampleFuContainer_table ( >> > >>>> id_AbstractContainer varchar(255) not null, >> > >>>> id varchar(255), >> > >>>> mysamplingmumble_ tinyblob, >> > >>>> uuid varchar(255), >> > >>>> primary key (id_AbstractContainer), >> > >>>> unique (id_AbstractContainer) >> > >>>> ); >> > >> > >>>> Best wishes, >> > >> > >>>> --greg >> > >> > >>>> On Mon, Jun 22, 2009 at 1:38 PM, Meredith Gregory < >> > >>>> lgreg.mered...@gmail.com> wrote: >> > >> > >>>>> Kris, >> > >> > >>>>> Thanks for the suggestion. i've now got a tiny little example that >> > >>>>> compiles on its own that illustrates the problem. Changing the >> inheritance >> > >>>>> strategy to JOINED makes no difference. Hibernate still does the >> wrong >> > >>>>> thing. >> > >> > >>>>> Best wishes, >> > >> > >>>>> --greg >> > >> > >>>>> On Mon, Jun 22, 2009 at 8:55 AM, Kris Nuttycombe < >> > >>>>> kris.nuttyco...@gmail.com> wrote: >> > >> > >>>>>> This may be off the mark, but I'm wondering if the reason that >> you're >> > >>>>>> having difficulty with the parallel inheritance hierarchy problem >> is >> > >>>>>> not your use of TABLE_PER_CLASS inheritance. In my application, I >> have >> > >>>>>> a similar construct, but I am using JOINED_TABLE inheritance. >> This >> > >>>>>> allows for a normal foreign key relationship to be created in the >> > >>>>>> database between C2_table and the base table for CThing, with the >> > >>>>>> result that Hibernate will generate the query for CThing member >> as a >> > >>>>>> union. Using table per class inheritance, I would expect >> Hibernate to >> > >>>>>> need to synthesize an additional dtype field in C2_table along >> with >> > >>>>>> the key column in order to enforce the uniqueness of the keys to >> the >> > >>>>>> joined entities, and I don't believe that it does this. >> > >> > >>>>>> I'm not sure how the fact that the code is generated is >> particularly >> > >>>>>> relevant; surely if it's possible to hand-write a successful >> solution, >> > >>>>>> then your code generator could be made aware of how to construct >> a >> > >>>>>> viable solution? >> > >> > >>>>>> Kris >> > >> > >>>>>> On Fri, Jun 19, 2009 at 8:47 PM, Meredith >> > >>>>>> Gregory<lgreg.mered...@gmail.com> wrote: >> > >>>>>> > All, >> > >> > >>>>>> > i had a similar problem and found the source of the issues. >> Spse you >> > >>>>>> have a >> > >>>>>> > container hierarchy (CTop <- C2) side-by-side with a contained >> > >>>>>> hierarchy >> > >>>>>> > (CThing <- CThing1). The inheritance at the top of the >> container >> > >>>>>> hierarchy, >> > >>>>>> > CTop, causes hibernate to bail on tracking the relations and >> punt to >> > >>>>>> > embedded values instead. Rewriting the top to be a >> @MappedSuperClass >> > >>>>>> fixes >> > >>>>>> > the problem in this specific case. However, if your hierarchy >> is >> > >>>>>> deep, >> > >>>>>> > you're screwed. >> > >> > >>>>>> > If anybody has a suggestion for a workaround, i'm all ears. The >> > >>>>>> problem is >> > >>>>>> > that it would appear that both Mr Crowley and i are generating >> Java >> > >>>>>> + JPA >> > >>>>>> > code. So, the solution needs to be algorithmic and not 1-off. >> > >> > >>>>>> > Perhaps the best solution is to find an alternative to >> hibernate as >> > >>>>>> this is >> > >>>>>> > a particularly irritating bug. >> > >> > >>>>>> > Best wishes, >> > >> > >>>>>> > --greg >> > >> > >>>>>> > @Entity >> > >>>>>> > @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) >> > >>>>>> > abstract class CTop { >> > >>>>>> > ... >> > >>>>>> > @Id >> > >>>>>> > @GeneratedValue(generator = "system-uuid") >> > >>>>>> > @GenericGenerator(name = "system-uuid", strategy = "uuid") >> > >>>>>> > private String id_CTop; >> > >>>>>> > } >> > >> > >>>>>> > @Entity >> > >>>>>> > @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) >> > >>>>>> > abstract class CThing { >> > >>>>>> > ... >> > >>>>>> > @Id >> > >>>>>> > @GeneratedValue(generator = "system-uuid") >> > >>>>>> > @GenericGenerator(name = "system-uuid", strategy = "uuid") >> > >>>>>> > private String id_CThing; >> > >>>>>> > } >> > >> > >>>>>> > @Entity >> > >>>>>> > @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) >> > >>>>>> > @Table(name = "C2_table", catalog = "mydb_production", >> > >>>>>> uniqueConstraints = { >> > >>>>>> > @UniqueConstraint(columnNames = "uuid") }) >> > >>>>>> > class C2 extends CTop { >> > >>>>>> > CThing thing; >> > >>>>>> > ... >> > >>>>>> > @OneToOne >> > >>>>>> > @JoinColumn >> > >>>>>> > public CThing getThing() { >> > >>>>>> > return this.thing; >> > >>>>>> > } >> > >>>>>> > public void setThing( CThing thing ) { >> > >>>>>> > this.thing = thing; >> > >>>>>> > } >> > >> > >>>>>> > @Column(name = "uuid", unique = false, nullable = true, >> insertable = >> > >>>>>> true, >> > >>>>>> > updatable = true) >> > >>>>>> > public String getUuid() { >> > >>>>>> > return this.uuid; >> > >>>>>> > } >> > >> > >>>>>> > public void setUuid(String uuid) { >> > >>>>>> > this.uuid = uuid; >> > >>>>>> > } >> > >> > >>>>>> > @Id >> > >>>>>> > @GeneratedValue(generator = "system-uuid") >> > >>>>>> > @GenericGenerator(name = "system-uuid", strategy = "uuid") >> > >>>>>> > @Column(name = "id", unique = false, nullable = true, >> insertable >> > >>>>>> = true, >> > >>>>>> > updatable = true) >> > >>>>>> > public String getId() { >> > >>>>>> > return this.id; >> > >>>>>> > } >> > >> > >>>>>> > } >> > >> > >>>>>> > @Entity >> > >>>>>> > @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) >> > >>>>>> > @Table(name = "CThing1_table", catalog = "mydb_production", >> > >>>>>> > uniqueConstraints = { @UniqueConstraint(columnNames = "uuid") >> }) >> > >>>>>> > class CThing1 extends CThing { >> > >>>>>> > ... >> > >>>>>> > // lots of ground type fields >> > >> > >>>>>> > @Column(name = "uuid", unique = false, nullable = true, >> insertable = >> > >>>>>> true, >> > >>>>>> > updatable = true) >> > >>>>>> > public String getUuid() { >> > >>>>>> > return this.uuid; >> > >>>>>> > } >> > >> > >>>>>> > public void setUuid(String uuid) { >> > >>>>>> > this.uuid = uuid; >> > >>>>>> > } >> > >> > >>>>>> > @Id >> > >>>>>> > @GeneratedValue(generator = "system-uuid") >> > >>>>>> > @GenericGenerator(name = "system-uuid", strategy = "uuid") >> > >>>>>> > @Column(name = "id", unique = false, nullable = true, >> insertable >> > >>>>>> = true, >> > >>>>>> > updatable = true) >> > >>>>>> > public String getId() { >> > >>>>>> > return this.id; >> > >>>>>> > } >> > >> > >>>>>> > } >> > >> > >>>>>> > On Tue, Jun 16, 2009 at 1:45 PM, Derek Chen-Becker < >> > >>>>>> j...@chen-becker.org> >> > >>>>>> > wrote: >> > >> > >>>>>> >> John Nilsson wrote: >> > >>>>>> >> > Hi, >> > >> > >>>>>> >> > I think the showSql property has been deprecated in favor of >> > >>>>>> log4j >> > >>>>>> >> > loggers. >> > >> > >>>>>> >> > If you set the log4j level to TRACE for org.hibernate you'll >> get >> > >>>>>> >> > everything Hibernate has to say about what >> > >> > ... >> > >> > read more ยป >> >> > > > > -- L.G. Meredith Managing Partner Biosimilarity LLC 1219 NW 83rd St Seattle, WA 98117 +1 206.650.3740 http://biosimilarity.blogspot.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~----------~----~----~----~------~----~------~--~---