Before persisting my entity I would like to check if it doesn't already exist according to three fields.
I know how to use the annotation "UniqueEntity" but it doesn't work for me because I can't use a conventional "formType".
To summarise, my question is: In symfony 2 what's the best way to perform a unique entity check in the controller?
I already thought about get an array of Id then use an "in_array" function to decide to persist my entity or not. But I'm not sure about the efficiency of that method.
I expect that entities that already exists in my database (according to 3 fields) are not persisted.
Thank you for your answers.
It's not a very good approach but if you can't use UniqueEntity, you can execute a findBy on your repository and decide to persist your entity or not.
$entityExists = $em->getRepository('MyBundle:MyEntity')->findBy(array('field1' => $value1,'field2' => $value2,'field3' => $value3));
Related
I'm aplying DDD in Laravel.
In this architecture, the entity (conformed by the corresponding value objects) is not a Laravel Model extended class (because the domain layer needs to be agnostic to the infrastructure)
So... when I retrieve some data inside the repository implementation, the result is a stdclass object, and I need to return it as the entity object.
Anybody knows the best approach to do this?
Thanks!
To get this, I tried to convert from stdclass to entity by manual, but it's look hacky and dirty.
Ok, got it.
I found two different approaches, just in case others are fighting with the same problem.
Option 1: Embracing the Eloquent Active Record.
Inside the infrastructure layer, I created a Eloquent model to represent the Entity, and I use it as a vehicule for eloquent queries. Like this, all the conection with the framework stay contained in the infrastructure, without polluting other layers.
Option 2: Apply Doctrine in Laravel.
Doctrine has a package for laravel. Doctrine, as occurs in Synfony, is using data mapping, so no worries with that.
Thanks anyway!
i’m new to spring when i try to update just one field of an entity I noticed in logs that hibernate perform two queries, before update it does a SELECT of all fields. Is that ok? Why does Hibernate perform that SELECT? How can i update a field with just one UPDATE query? Additionally when I tried to update a single title in an entity that has another nested entity i end up with a bunch of SELECT. I think it’s not good for performance or I’m wrong?
Something s = somethingRepository.findById(id);
s.setField1(someData);
somethingRepository.save(s);
On the internet I found a solution to make custom query with #Modifying and #Query(“UPDATE …”) but in this way I need to make custom query for every single field. Is there a better solution?
As per the source code you have pasted in the question
Something s = somethingRepository.findById(id);
s.setField1(someData);
somethingRepository.save(s);
if the entity Something which you are asking does not exist in the hibernate first level cache, it will make one SELECT call.
and as you are updating field 1 value then it will make another update call.
It does not matter if you are using save or not because Hibernate dirty checks will ensure that all changes are updated.
otherwise you can use custom method with #Modifying with JPQL and named params. It is more readable than ?1,
#Modifying
#Query("UPDATE Something s SET s.field = :fieldValue WHERE s.id = :id")
void updateField(String fieldValue, UUID id);
Regarding that you are seeing multiple calls "when I tried to update a single title in an entity that has another nested entity". It depends on how you have created the relationship among entities. If you can share the entities and their relationship then only it can be answered accurately.
Because internally the repository.save() method does an upsert. If you go to the inner classes and check you will see that first, it will check whether the entity is present in the database then based on that it will perform add or update. If you don't want the SELECT query to run then you can use the native query offered by the JPA repository. You can do something like this:
#Modifying
#Transactional
#Query("UPDATE <tableName> SET <columnName> = ?1 WHERE <condition>" ,nativeQuery=true)
void updateSomething(String value);
Suppose if I have 3 entities - User, Skills, Department
and I have repositories corresponding to all of them - UserRepository, SkillRepository, DepartmentRepository.
I understand that the relation mapping between entities i.e. one-one many-many should be specified in the respective entity classes. The question is I want to use all of the 3 entities in a query. How would I do it? A single repository is associated with only one entity right? So, how/where would I write it?
As there are many different ways to specify queries with Spring Data JPA there are various answers to this.
Maybe you don't have to. If entity A references B and you just want to get the Bs with your A you simply use your ARepository to load As and use object navigation to get your Bs. You might read up on eager and lazy loading for more information about how to control this.
If you want referenced entities in the where condition you can use property paths in your query method names: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-property-expressions
If you are using #Query annotations you can do (almost) whatever you want with JPQL. Among others, you may as well navigate properties to use them in where clauses.
In general, you'd put that query in the matching repository based on the primary entity returned.
I have defined a many-to-many relationship between Student and Seminar models. How can I find out if one particular student is attending one particular seminar? Non-working example of what I want to achieve is illustrated below:
$seminar->students()->contains($student->id);
The following error is shown when using the above code snippet:
BadMethodCallException with message 'Call to undefined method Illuminate\Database\Query\Builder::contain()'
Try instead:
$seminar->students->contains($student->id);
Presuming $student contains an instance of the Student model you can simplify it further and just use:
$seminar->students->contains($student);
When you add parentheses you're using the Laravel query builder, and you never completed the query. To do it in the manner you had originally you would need:
$seminar->students()->get()->contains($student->id);
This method could be useful if you wanted to add constraints when fetching your students.
But generally you can omit the parentheses and a Collection will be returned, allowing you to use methods like contains.
This has the additional benefit of not re-querying the database once the relationship is loaded, so will generally be a far more efficient means of fetching relationships.
If you haven't already loaded the students and want a database efficient method of checking you could instead use:
$seminar->students()->where('students.id', $student->id)->exists();
In your case the exception is you are calling 'contains()' function (which is for Laravel Collection) on 'Query Builder'. It should be
$seminar->students->get()->contains($student->id);
but this is inefficient since this will retrieve all the students of the seminar.
so instead,
$seminar->students()->wherePivot('student_id', $student->id)->exists();
this method will check in the intermediate table of many to many relationship for particular seminar-student pair, and will return whether exists or not.
The accepted answer is wrong. $seminar->students()->exists($student->id) does not check if the relationship exists. It only checks if the student exists. The student could belong to any seminar and it would still return true.
The correct way to check if a relationship exists without fetching records from the database would be:
$seminar->students()->whereId($student->id)->exists()
Check using query
$seminar->students()->whereKey($student->getKey())->exists();
Check after query (angry), can have memory problems if you have multiple attachments
$seminar->students->contains($student->getKey());
// or
$seminar->students()->get()->contains($student->getKey());
is there any method for inserting new record or update when record exists in database using DB facade ?
Note: there is no model but only a controller , so using model related methods is impossible.my question is regards to query builder
The most straightforward approach is to look into your database's syntax for upserting. It will be different depending on the database and the specific situation, and may require defining a UNIQUE key of some kind.
Here is an example for MySQL:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
By the way, the more idiomatic approach would be to define a model. Model's allow you to handle this situation more gracefully and (in many cases) prevent you from tying your code to a specific RDBMS.