cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Hans C. Poo" <h...@welinux.cl>
Subject Re: Table and entity refactor breaks relationships
Date Mon, 21 Feb 2011 14:38:29 GMT
Hi,

Andrus, thanks for your time, i'm using cayenne 3.0.1

Testing in detail the problem arises when the association is between tables in distinct schemas,
when the are in the same schema all is fine.

Here i have tow tables:region and user in two different schemas, each user has an associated
region, and in reverse, each region is associates with many users. 

If you change the name of the table user, for example to person, you see the next errors:

ObjRelationship <Region.users> has incomplete DbRelationship mapping.
DbRelationship <region.users> has no target entity.


cayenne.xml
-------------
<?xml version="1.0" encoding="utf-8"?>
<domains project-version="3.0.0.1">
<domain name="testProject">
	<property name="cayenne.DataRowStore.snapshot.size" value="50000"/>

	<map name="geoMap" location="geoMap.map.xml"/>
	<map name="identMap" location="identMap.map.xml"/>

	<node name="testProjectNode"
		 datasource="testProjectNode.driver.xml"
		 factory="org.apache.cayenne.conf.DriverDataSourceFactory">
			<map-ref name="identMap"/>
			<map-ref name="geoMap"/>
	 </node>
</domain>
</domains>

codewebNode.driver.xml
-------------
<?xml version="1.0" encoding="utf-8"?>
<driver project-version="3.0.0.1" class="org.postgresql.Driver">
	<url value="jdbc:postgresql://localhost:5432/testProject"/>
	<connectionPool min="1" max="100"/>
	<login userName="testProject" password="123456"/>
</driver>

geoMap.map.xml
-------------
<?xml version="1.0" encoding="utf-8"?>
<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://cayenne.apache.org/schema/3.0/modelMap http://cayenne.apache.org/schema/3.0/modelMap.xsd"
  project-version="3.0.0.1">
	<property name="defaultPackage" value="cl.test.geo"/>
	<property name="defaultSchema" value="geo"/>
	<db-entity name="region" schema="geo">
		<db-attribute name="id" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
		<db-attribute name="name" type="VARCHAR" isMandatory="true" length="128"/>
	</db-entity>
	<obj-entity name="Region" className="cl.test.geo.Region" dbEntityName="region">
		<obj-attribute name="name" type="java.lang.String" db-attribute-path="name"/>
	</obj-entity>
	<db-relationship name="users" source="region" target="user" toMany="true">
		<db-attribute-pair source="id" target="id_region"/>
	</db-relationship>
	<obj-relationship name="users" source="Region" target="User" deleteRule="Deny" db-relationship-path="users"/>
</data-map>

identMap.map.xml
-------------
<?xml version="1.0" encoding="utf-8"?>
<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://cayenne.apache.org/schema/3.0/modelMap http://cayenne.apache.org/schema/3.0/modelMap.xsd"
  project-version="3.0.0.1">
	<property name="defaultPackage" value="cl.test.ident"/>
	<property name="defaultSchema" value="ident"/>
	<db-entity name="user" schema="ident">
		<db-attribute name="active" type="BOOLEAN" isMandatory="true"/>
		<db-attribute name="id" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
		<db-attribute name="id_region" type="INTEGER" isMandatory="true"/>
		<db-attribute name="name" type="VARCHAR" isMandatory="true" length="128"/>
	</db-entity>
	<obj-entity name="User" className="cl.test.ident.User" dbEntityName="user">
		<obj-attribute name="active" type="java.lang.Boolean" db-attribute-path="active"/>
		<obj-attribute name="name" type="java.lang.String" db-attribute-path="name"/>
	</obj-entity>
	<db-relationship name="region" source="user" target="region" toMany="false">
		<db-attribute-pair source="id_region" target="id"/>
	</db-relationship>
	<obj-relationship name="region" source="User" target="Region" deleteRule="Nullify" db-relationship-path="region"/>
</data-map>

testProjectNode.driver.xml
-------------
<?xml version="1.0" encoding="utf-8"?>
<driver project-version="3.0.0.1">
	<connectionPool min="1" max="1"/>
	<login/>
</driver>



Hans

Hans Poo, Welinux S.A.
Bombero Ossa #1010, oficina 526, 
+56-2-3729770, Movil: +56-9-3199305
Santiago, Chile


----- Mensaje original -----
De: "Andrus Adamchik" <andrus@objectstyle.org>
Para: user@cayenne.apache.org
Enviados: Domingo, 20 de Febrero 2011 12:43:36
Asunto: Re: Table and entity refactor breaks relationships

I haven't seen the Modeler breaking relationships on renaming the tables/classes. Which version
of Cayenne are you using, and if it is 3.0 or newer, what is the exact scenario - maybe we
need a Jira for it?

Beyond that it is all a matter of preference, so as long as you keep in mind all the pieces
involved, there can be more than one way to refactor things. I'd usually manually write a
SQL script that changes the DB and commit it to version control (as it will need to be rerun
in QA/production later on the next release). Then I'd perform needed renaming in the Modeler,
then refresh my project in Eclipse (that triggers Maven class generation), and then delete
classes no longer in use.

Andrus


On Feb 18, 2011, at 5:58 PM, Hans C. Poo wrote:
> Hi,
> 
> I've been using cayenne three years from now.
> 
> Using the modeller i tried to rename a table and then a class with distinct levels of
problems with broken relationships. Until i see the modeller does atempts to refactor some
things but many gets broken.
> 
> I've found a tricky method to refactor things with relative confidence:
> 
> First:
> 
> 1.- Classes
> Rename classes: the entity and the cayenne entity (underscore first character) using
the refactor capabilities of your IDE.  
> 
> 2.- XML files
> Here it's a very artesanal perl script that refactor a table and the related entity.
If you call it refactor-table-name.pl you can call it this way:
> 
> Move where cayenne files are located and:
> 
> refactor-table-name.pl old-table-name new-table-name *.xml
> 
> 3.- So far some things still may be broken
> 
> Then open the modeller and your project, the use Project > Validate Project there
may be the broken object relationships, these must be deleted an re-synchronised and will
be fine.
> 
> 4.- Database
> Finally: rename the table in the database using alter table.
> 
> 
> Please if there is some better, safer way to do it please let me know.
> 
> The code of the perl script follows. Save it under your bin directory and name it refactor-table-name.pl,
then chmod 755 refactor-table-name.pl.
> 
> #!/usr/bin/perl
> 
> 
> ## Refactor cayenne table and entity, give table names assumed parts of the name separated
by underscores.
> ## Use under your own risk on a copy of your data.
> 
> use strict;
> use warnings;
> 
> use File::Copy; 
> 
> die "Error, call format: $0 old-table-name new-table-name file1 [ .. more files ] "	if
@ARGV < 3;
> 
> my $old_name = shift;
> my $new_name = shift;
> 
> # extrapolar object names
> 
> my $old_name_obj = "";
> foreach (split /_/, $old_name) {
> 	$old_name_obj .= ucfirst($_);
> }
> 
> my $new_name_obj = "";
> foreach (split /_/, $new_name) {
> 	$new_name_obj .= ucfirst($_);
> }
> 
> my @files = @ARGV;
> 
> printf "Renaming table %s to %s\n", $old_name, $new_name;
> printf "Renaming clase %s to %s\n", $old_name_obj, $new_name_obj;
> 
> my $i = 1;
> foreach my $file (@files) {
> 
> 	print "Processing file $file\n";
> 
> 	open IN, $file or die "File $file, error $!\n";
> 	
> 	my $tmp = "/tmp/refactor-$i-cayenne-$$";
> 	$i++;
> 
> 	open TMP, ">$tmp" or die "File $file, error $!\n";
> 
> 	my $flag_modif = 0;
> 
> 	while (<IN>) {
> 
> 		my $orig_line = $_;
> 
> 		s/db-entity name="$old_name"/db-entity name="$new_name"/;
> 		s/dbEntityName="$old_name"/dbEntityName="$new_name"/;
> 		s/target="$old_name"/target="$new_name"/;
> 		s/source="$old_name"/source="$new_name"/;
> 		s/db-relationship-path="$old_name"/db-relationship-path="$new_name"/;
> 		s/dbEntityName="$old_name"/dbEntityName="$new_name"/;
> 
> 
> 		s/<obj-entity name="$old_name_obj"/<obj-entity name="$new_name_obj"/;
> 		s/className="(.*?)\.$old_name_obj"/className="$1.$new_name_obj"/;
> 		s/source="$old_name_obj"/source="$new_name_obj"/;
> 		s/target="$old_name_obj"/target="$new_name_obj"/;
> 
> 		$flag_modif = 1		if $orig_line ne $_;
> 
> 		print TMP $_;
> 
> 	}
> 
> 	close IN;
> 	close TMP;
> 
> 	if ($flag_modif == 1) {
> 		print "\t * File modified\n";
> 		copy $tmp, $file or die $!;
> 	 }
> 
> }
> 
> 
> exit 0;
> 
> 
> 
> Bye
> Hans, Welinux S.A.
> 
> 


Mime
View raw message