typo3 flow persist updated relation - doctrine-orm

I have an issue TYPO3 Flow updating my relations.
Am I wrong, that Flow should update changed relations automatically, so I don't have to update the related entities with the respective repository?
Example 1:
I have a model "Project" with multiple "Job" childs on attribute "jobs".
If I do:
$project->setJobs($collectionOfJobs);
$this->projectRepository->update($project);
then jobs are not updated correctly with the new project-id.
Example 2:
I wanted to realize a bidirectional one-to-one relationship between the models "Project" and "Briefing" and found out, that there is a known bug in TYPO3:
Bidirectional One-To-One Relationships in Flow
So I wanted to to fix it with setting the relation on the other side manually:
class Briefing {
/**
* #param \Some\Package\Domain\Model\Project $project
* #return void
*/
public function setProject($project) {
$this->project = $project;
$this->project->setBriefing($this);
$this->projectRepository->update($this->project); // FIXME: Bug? Flow should do this
}
but I had to update the relation with its repository by self. Shouldn't Flow do this automatically?
So do I really need to update each child with its repository by self or should Flow do this for me?
Environment:
- TYPO3 FLOW 2.3.3 (latest stable)
- Doctrine 2.3.6
- PHP 5.4.39-0+deb7u2

From the Flow manual:
When you add or remove an object to or from a repository, the object will be added to or removed from the underlying persistence as expected upon persistAll. But what about changes to already persisted objects? As we have seen, those changes are only persisted, if the changed object is given to update on the corresponding repository.
Now, for objects that have no corresponding repository, how are changes persisted? In the same way you fetch those objects from their parent - by traversal. TYPO3 Flow follows references from objects managed in a repository (aggregate roots) for all persistence operations, unless the referenced object itself is an aggregate root.
So if there is a repository for your entity, you must explicitely call the update method. This was different originally but changed for Flow 1.0.
Maybe you think that this should work because it worked in TYPO3 CMS Extbase < 6.2 until it was changed there, too.

Related

Non-backwards compatible state upgrade in Corda using SignatureConstraint

I want to perform a non-backwards compatible state upgrade using SignatureConstraint. If it were a backwards compatible change, for example adding a property, I'd just added a nullable property in the state and that would work. However I don't have any idea how should I act in the following scenarios:
Scenario1: A new non-null field is added to the state
Scenario2: A field was removed from state
Scenario3: A field was modified in the state. E.g. a field of type Date transformed into an object which contains that date and some other fields.
Scenario4: A field in the state was renamed.
The problem is that explicit upgrade does not support SignatureConstraint and I get the following error message Legacy contract does not satisfy the upgraded contract's constraint, so I need to find a solution for implicity upgrade.
ContractUpgradeFlow doesn't support the upgrade of state with SignatureConstraint. However, the flexibility of Signature Constraint allows you to add any CorDapps as long as it's signed by the same key. You could easily write a simple flow to mimic an ExplicitUpgrade for the scenario you mentioned.
Here is what you could do:
Add both the corDapps jar files (old and updated) in the nodes cordapps folder.
Write another cordapp with a flow that consumes your existing state and outputs the new state (the upgraded one).
Add this flow jar to the nodes cordapps folder.
Execute the new flow to consume the older states and output the upgraded state.
Points to Note:
Make sure to have the correct set of signers to avoid incorrect spending of the states.
This is just an overall idea. The actual way of doing this might get a little complicated depending on the contract rules for your Exit transaction of the state.
I would rather add a new upgrade command to cater to this scenario.
You could have got the overall idea and do the tweaking at your end to perform the upgrade of your usecase. Hope this helps!
As a workaround I made the incompatible change to become a compatible one. Here is how it works.
I've created a state which has propertiesV1 object. This object includes all the fields that CompanyState should.
#CordaSerializable
#BelongsToContract(CompanyContract::class)
data class CompanyState(
override val linearId: UniqueIdentifier,
val propertiesV1: CompanyV1?
) : LinearState
Now when I need to make an incompatible change in the properties, I just add another version of the object to the state.
#CordaSerializable
#BelongsToContract(CompanyContract::class)
data class CompanyState(
override val linearId: UniqueIdentifier,
val propertiesV1: CompanyV1?,
val propertiesV2: CompanyV2?
) : LinearState
Neither contract, nor flows are changed. They are just being updated to handle propertiesV2 field.

Symfony & Doctrine: Optional foreign key

Without scrutinizing why I want this (it may sound like a bad approach, but I have good reason) I want to know if there is a way in the standard-framework-edition 3.1+ to create a relational association to an entity that may not exist...
Firstly I do realize this determines the schema and that's fine. So if an entity does not exist, it doesn't create a foreign key and the field is always null, or if the target entity does exist, it creates the foreign key and the field works like a normal association...
Secondly, this only changes project to project, and may change down the line as an update to which I realize a manual schema update could be necessary.
Preferably without 3rd party bundle dependencies... hoping for the standard framework to do this,
Anybody?
Thanks in advance
Edit
I am using annotations in my entities with doctrine ORM
Furthermore
The simplest version of why I am doing this is because certain bundles are optional project-to-project, and bundle A may make use of entities in bundle B only if it is present. I have considered using services and if container->has then container->get, or the XML on-invalid="null" approach, but that doesn't address property persistence. I was happy with storing a non-mapped value as a custom relational field, which is fine, just lengthier and wondered if perhaps there was a way Doctrine could ignore a missing targetEntity...
Hm, perhaps I misunderstand your question, but this sounds like a normal 'nullable' association to me?
Create your assocation via annotation:
/**
*
* #var Child
* #ORM\ManyToOne(targetEntity="Child")
*/
private $child;
and use
setChild(Child $child = null)
{
$this->child = $child;
}
as a Setter to allow nullable values.
And your getter might look like:
getChild()
{
return $this->child;
}
In case there isn't any child it will return null.
I will keep the other answer as it responds to the question for a 'nullable association target' live data.
This is the answer for a 'nullable association target' meta data which is a different thing.
OP asks to provide a targetEntity in the metadata which cannot exist in his case, e.g. is not there in a different bundle (or whatever OP's mysterious reason might be).
In that case I recommend to build upon Doctrine's TargetEntityListener which is able to resolve the targetEntity during runtime and targetEntity can be set to an Abstract Class or an Interface:
/**
* #ORM\ManyToOne(targetEntity="Acme\InvoiceBundle\Model\InvoiceSubjectInterface")
* #var InvoiceSubjectInterface
*/
protected $subject;
InvoiceSubjectInterface will then be replaced during runtime by a specific class provided by config e.g.:
# app/config/config.yml
doctrine:
# ...
orm:
# ...
resolve_target_entities:
Acme\InvoiceBundle\Model\InvoiceSubjectInterface: AppBundle\Entity\Customer
So this should be eiter an extendable behaviour for providing no class or implementing an own solution.

How to change Sitecore Template field Item Id without data loss?

I recently noticed there is a difference in Item Id for a Sitecore template field between 2 environments (Source and Target). Due to this, any data changes to the field value for the dataitem using the template is not reflecting to target Sitecore database.
Hence, we manually copy the value from source to target and which takes lot of time to sync the 2 environments. Any idea how to change the template field Item Id in Sitecore without data loss in target instance?
Thanks
The template fields have most likely been created manually on the different servers, as #AdrianIorgu has suggested. I am going to suggest that you don't worry about merging fields and tools.
What you really care about is the content on the PRODUCTION instance of your site (assuming that this is Target). In any other environment, content should be regarded throwaway.
With that in mind, create a package of the template from your PRODUCTION instance and the install that in the other environments, deleting the duplicate field from the Source instance. The GUIDs of the field should now match across all environments. Check this into your source control (using TDS or Unicorn or whatever). You can then correctly update any standard values and that will be reflect through the server when you deploy again.
If your other environments (dev/qa/pre-prod) result in data loss for that field then don't worry about it, restore a backup from PROD.
Most likely that happened because the field or the template was added manually on the second environment, without migrating the items using packages, serialization or a third-party tool like TDS or Unicorn.
As #SitecoreClimber mentioned above, you can use Razl to sync the two environments and see the differences, but I don't think you will be able to change the field's GUID, to have the two environments consistent, without any data loss. Depending on the volume of your data, fixing this can be tricky.
What I would do:
make sure the target instance has the right template by installing a package with the correct template from source (with a MERGE-MERGE operation), which will end up having a duplicate field name
write a SQL query to get a list of all the items that have value for that field and update the value to the new field
Warning: this SQL query below is just a sample to get you started, make sure you extend and test this properly before running on a CD instance
use YOUR_DATABASE
begin tran
Declare #oldFieldId nvarchar(100), #newFieldId nvarchar(100), #previousValue nvarchar(100), #newValue nvarchar(100)
set #oldFieldID = '75577384-3C97-45DA-A847-81B00500E250' //old field ID
set #newFieldID = 'A2F96461-DE33-4CC6-B758-D5183676509B' //new field ID
/* versionedFields */
Select itemId, fieldid, value
from [dbo].[versionedFields] f with (nolock)
where f.FieldId like #oldFieldID
For this kind of stuff I sugest you to use Sitecore Razl.
It's a tool for comparing and merging sitecore databases.
Razl allows developers to have a complete side by side comparison between two Sitecore databases; highlighting features that are missing or not up to date. Razl also gives developers the ability to simply move the item from one database to another.
Whether it's finding that one missing template, moving your entire database or just one item, Razl allows you to do it seamlessly and worry free.
It's not a free tool, you can check here how you can buy it:
https://www.razl.net/purchase.aspx

Entity Framework 5 - Migrations and creating table from entity

I am using Entity Framework 5 RC and i have some code that require a specific table on the database. The entity is already created using Code-First.
a) Is there a way to tell EF to create the table if its not already created in the database ? If yes.. how ?
b) Also.. if the table already exist, can it handle entity changes such adding properties to the entity.. will it get reflected on the database ? (We still use the code-first approach here)
Thanks!
Use code first migrations (either automatic or code based). If you are adding table to existing database create initial migration first and than add your new entity. All links are for EF 4.3 but the usage is exactly the same in EF 5.
For reference for anyone else having this problem, I had the same problem and my solution is here
Entity Framework: Generating specific table if doesn't exist?

OpenJPA CascadeType.DELETE causes Foreign Key constraint violation

I am using OpenJPA (JPA 1.0) on WebLogic 10.0.x with Oracle. I have defined a OneToMany relationship as below:
#Entity
public class Compound implements Serializable {
...
#OneToMany(mappedBy="compound", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
private List<Submission> submissions = new ArrayList<Submission>();
...
}
#Entity
public class Submission implements Serializable {
...
#ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.REFRESH)
#JoinColumn(name="compoundId")
private Compound compound;
...
}
When I delete a Compound entity all child Submission entities should be deleted also. This works as a general rule, except that I have a foreign key constraint setup on these tables:
ALTER TABLE SUBMISSION
ADD CONSTRAINT FK_SUBMISSION_COMPOUND
FOREIGN KEY (COMPOUNDID)
REFERENCES COMPOUND(COMPOUNDID);
Now when I attempt to delete the Compound entity I encounter the following exception:
ORA-02292: integrity constraint (HELC.FK_SUBMISSION_COMPOUND) violated - child record found {prepstmnt 3740 DELETE FROM Compound WHERE compoundId = ? [params=(long) 10384]} [code=2292, state=23000]"
The above exception implies that Open JPA is attempting to delete the parent prior to cascading the delete onto the child entities. I've read a few articles via Google about this exception, dating back to 2006. However, the most recent article suggests that this bug has been fixed?
http://mail-archives.apache.org/mod_mbox/openjpa-dev/200609.mbox/%3C14156901.1158019042738.JavaMail.jira#brutus%3E
https://issues.apache.org/jira/browse/OPENJPA-235
Can anyone suggest why this is not working and what I can do about it? I am loathe to manually delete the child entities, especially as this is one of the less-complicated relationships in my schema and whatever solution I use for this I will need to apply elsewhere.
Thanks
Jay
When I delete a Compound entity all child Submission entities should
be deleted also. This works as a general rule, except that I have a
foreign key constraint setup on these tables:
If you can change the foreign key constraint, that should solve the problem as far as the database is concerned. I'm not sure how OpenJPA will behave here.
ALTER TABLE SUBMISSION
ADD CONSTRAINT FK_SUBMISSION_COMPOUND
FOREIGN KEY (COMPOUNDID)
REFERENCES COMPOUND(COMPOUNDID)
ON DELETE CASCADE;
One thing - as discussed above this is Weblogic 10.0.x. I suspect we
are using the bundled version of OpenJPA / Kodo, which is probably
quite old...
My own feeling is that the bug you referred to should have been fixed by this version, but it's also a) close enough in time that it might not have been fixed, and b) potentially a big enough problem that I think you should spend some time verifying the version and fix. (Actually, I just noticed that OpenJPA 1.0 was released on Aug 2007. That's a lot earlier than I thought, which makes it more likely you don't have the bug fix.)
If you can't modify the database (because it's a legacy system that clearly doesn't intend for clients to rely on cascading deletes), and if the bug isn't fixed in your version, you'll have to manage the order of SQL statements yourself.
The burden of manually managing SQL statements--which is one of the things that OpenJPA is supposed to do for you--might be enough to get management to either upgrade OpenJPA or to update the foreign key constraints in the database.
I really hope you get a better answer than this one.