Spring JDBCTemplates: execute a query with Join - sql

I'm developing an app for DB querying, using Spring Boot and JDBCTemplates.
The problem is this: if I have to ask the db on a single table, I have no problems. But, if I have a join, how can I perform this task?
More specifically, the SQL commands to create tables are these:
CREATE TABLE firewall_items
(
id INT NOT NULL AUTO_INCREMENT,
firewall_id INT NOT NULL,
date DATE,
src VARCHAR(15),
src_port INT,
dst VARCHAR(15),
dst_port INT,
protocol VARCHAR(4),
PRIMARY KEY(id)
);
CREATE TABLE firewalls (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
ip VARCHAR(15) NOT NULL,
info TEXT,
PRIMARY KEY(id)
);
The correspondings java class are these:
import java.util.Date;
public class FirewallItems
{
private Date date;
private String id;
private String protocol;
private String src;
private String dst;
private String src_port;
private String dst_port;
private String firewall_id;
public FirewallItems() {}
public FirewallItems(Date data, String identificativo, String protocollo, String sorgente, String destinazione,
String porta_sorgente, String porta_destinazione, String firewall_id)
{
super();
this.date = data;
this.id = identificativo;
this.protocol = protocollo;
this.src = sorgente;
this.dst = destinazione;
this.src_port = porta_sorgente;
this.dst_port = porta_destinazione;
this.firewall_id = firewall_id;
}
/**
* Return the date of the report
* #return date
*/
public Date getDate()
{
return date;
}
/**
* Set the date of the report
* #param date the report's date
*/
public void setDate(Date date)
{
this.date = date;
}
/**
* Return the id of the report
* #return id
*/
public String getId()
{
return id;
}
/**
* Set the id of the report
* #param id the report's id
*/
public void setId(String id)
{
this.id = id;
}
/**
* Return the protocol cecked by report
* #return protocol
*/
public String getProtocol()
{
return protocol;
}
/**
* Set the protocol cecked by report
* #param protocol
*/
public void setProtocol(String protocol)
{
this.protocol = protocol;
}
/**
* Return the source of firewall's drop
* #return Src
*/
public String getSrc()
{
return src;
}
/**
* Set the source of firewall's drop
* #param src the firewall's source drop
*/
public void setSrc(String src)
{
this.src = src;
}
/**
* Return the firewall's destionation drop
* #return dst
*/
public String getDst()
{
return dst;
}
/**
* Set the firewall's destination drop
* #param dst the firewall's destination drop
*/
public void setDst(String dst)
{
this.dst = dst;
}
/**
* Return the source's port
* #return src_port
*/
public String getSrc_port()
{
return src_port;
}
/**
* Set the source's port
* #param src_port the source's port
*/
public void setSrc_port(String src_port)
{
this.src_port = src_port;
}
/**
* Return the destination's port
* #return dst_port
*/
public String getDst_port()
{
return dst_port;
}
/**
* Set the destination's port
* #param dst_port the destination's port
*/
public void setDst_port(String dst_port)
{
this.dst_port = dst_port;
}
/**
* Return the id of firewall associated to report
* #return firewall_id
*/
public String getFirewall_id()
{
return firewall_id;
}
/**
* Set the id of firewall associated to report
* #param firewall_id the id of firewall associated to report
*/
public void setFirewall_id(String firewall_id)
{
this.firewall_id = firewall_id;
}
}
public class Firewall
{
private String id;
private String ip;
private String info;
private String name;
/**
* Empty constructor, which instantiates a Firewall specimen without setting default values
*/
public Firewall() {}
/**
* Constructor instantiating a Firewall specimen specifying its initial values
*
* #param id the firewall's id code
* #param ip the firewall's ip code
* #param info the info about firewall
* #param name firewall's name
*/
public Firewall(String id, String ip, String info, String nome)
{
super();
this.id = id;
this.ip = ip;
this.info = info;
this.name = nome;
}
/**
* Return the firewall's id
* #return id
*/
public String getId()
{
return id;
}
/**
* Set firewall's id
* #param id the firewall's id
*/
public void setId(String id)
{
this.id = id;
}
/**
* Return the firewall's ip
* #return ip
*/
public String getIp()
{
return ip;
}
/**
* Set firewall's ip
* #param ip the firewall's ip
*/
public void setIp(String ip)
{
this.ip = ip;
}
/**
* Return firewall's info
* #return info
*/
public String getInfo()
{
return info;
}
/**
* Set firewall's info
* #param info firewall's info fields
*/
public void setInfo(String info)
{
this.info = info;
}
/**
* Return firewall's name
* #return name
*/
public String getName()
{
return name;
}
/**
* Set firewall's name
* #param name firewall's name
*/
public void setName(String name)
{
this.name = name;
}
}
The constraint is that firewall_Items.firewall_id = firewall.id (so, these are the variables that i must use to perform join).
Now, if i want perform this query:
SELECT info, src
FROM firewalls, firewall_items
WHERE firewall_items.firewall_id = firewalls.id;
How my java code must be, using jdbctemplate?
Should i add to firewall class a collection to collect object of FirewallsItems, like an ArrayList?
Note1: i must use jdbctemplate project specifications. I can't use Hibernate or other instruments.
Note2: I know what rowmapper and resultset are, i regolary use them with query on a single table. What i nedd is to understand how to use them for a query with join, like that of the example.
Thanks a lot in advance for response!

you should use the JOIN keyword to join your tables before you query them.
Like so:
String query= "SELECT firewall_items.src, firewalls.info
FROM firewall_items
JOIN firewalls
ON firewall_items.firewalls_id = firewalls.id"
List<Item> items = jdbcTemplate.query(
query,
new MapSqlParameterSource(),
new FirewallInfoRowMapper()
);
Where Item is your retrieved object. You decide what that is.
Look at this article for more info
EDIT:
In response to your further inquiry. Above is the amended usage of jdbcTemplate, below you can find the classes you need. This requires you to have Spring.
I've assumed that if you're using jdbcTemplate you already have Spring.
Below is a cheat sheet, but please look at this site and learn more about querying databases with java Spring and jdbcTemplates.
The correct implementation for a row mapper is like so :
public class FirewallInfoRowMapper implements RowMapper<FirewallInfo>{
#Override
public FirewallInfo mapRow(ResultSet rs, int rowNum) throws SQLException{
return new FirewallInfo(rs.getString("src"), rs.getString("info"))
}
}
public class FirewallInfo{
private String src;
private String info;
public FirewallInfo(String src, String info){
this.src = src;
this.info = info;
}
{}<<< Getters and Setters Here
}

I know its late. There aren't a lot of good tutorial out there so incase someone else needs to know how to execute join query with spring and jdbc template. This is the way I did mine.
First ensure to import the following jars in your dao class like so
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
Then in your FirewallDao class, do something like
public List<Firewall> getData(){
return template.query("SELECT firewalls.info, firewall_items.src FROM firewalls INNER JOIN firewall_items ON firewall_items.firewall_id = firewalls.id",new RowMapper<Firewall>(){
public Firewall mapRow(ResultSet rs, int row) throws SQLException {
Firewall f =new Firewall();
f.setInfo(rs.getString(1));
f.setSrc(rs.getString(2));
return f;
}
});
}
In you controller, something like
#Autowired
FirewallDao dao;
#RequestMapping("/viewinfo")
public ModelAndView viewinfo(){
List<Firewall> list=dao.getData();
return new ModelAndView("viewinfo","list",list);
}
in ur view, do something like
<table border="2" width="70%" cellpadding="2">
<tr><th>Info</th><th>Src</th></th><th>Edit</th></tr>
<c:forEach var="f" items="${list}">
<tr>
<td>${f.info}</td>
<td>${f.src}</td>
</tr>
</c:forEach>
</table>

Related

ApiPlatform: How to update instead of create a child entity that is not a #ApiResource nor a #ApiSubresource

I have a ThirdPartyEntity from a third party bundle that, using a ThirdPartyEntityTrait, I link to MyEntity in my project.
Now, as the ThirdPartyEntity is not set a ApiResource nor as an ApiSubresource and as I don't have any serializaton group set on MyEntity, when I get MyEntity from ApiPlatform, it returns me something like this:
{
"#id":"/api/my_entities/17",
"#type":"MyEntity",
"id":17,
"third_party_entity": {
"id":22,
"a_property":"some value"
}
}
BUT IF I PUT a changed value for a_property with this body:
{
"#id":"/api/my_entities/17",
"#type":"MyEntity",
"id":17,
"third_party_entity": {
"id":22,
"a_property":"some NEW value to update"
}
}
I get a new third_party_entity to be created and get this response:
{
"#id":"/api/my_entities/17",
"#type":"MyEntity",
"id":17,
"third_party_entity": {
"id":23,
"a_property":"some NEW value to update"
}
}
SO, HOW CAN I UPDATE third_party_entity instead of creating it each time?
HERE THERE ARE THE INVOLVED CLASSES AND TRAITS
/**
* #ORM\Table(name="app_my_entities")
* #ORM\Entity()
* #ApiResource()
*/
class MyEntity
{
// !!!!!!!!!!!!!!!!!!
// This is the trait I use to link MyEntity
// with the entity from the third-party bundle
// !!!!!!!!!!!!!!!!!!
use ThirdPartyEntityTrait;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
...
}
And this is the ThirdPartyEntityTrait:
trait ThirdPartyEntityTrait
{
/**
* #ORM\OneToOne(targetEntity="Namespace\To\Bundle\Entity\ThirdPartyEntity", cascade={"all"})
* #ORM\JoinColumn(name="thirdPartyEntity", referencedColumnName="id")
*/
private $thirdPartyEntity;
/**
* #param thirdPartyEntity $thirdPartyEntity
*
* #return ThirdPartyEntity
*/
public function setThirdPartyEntity(thirdPartyEntity $thirdPartyEntity): ThirdPartyEntity
{
$this->thirdPartyEntity = $thirdPartyEntity;
/** #var ThirdPartyEntity $this */
return $this;
}
/**
* #return thirdPartyEntity
*/
public function getThirdPartyEntity(): ?thirdPartyEntity
{
return $this->thirdPartyEntity;
}
/**
* #return thirdPartyEntity
*/
public function removeThirdPartyEntity(): ?thirdPartyEntity
{
$thirdPartyEntity = $this->getThirdPartyEntity();
$this->thirdPartyEntity = null;
return $thirdPartyEntity;
}
}
As you can see, nothing more a property to save the relation and some accessors methods.
This is, instead, the linked Entity:
/**
* #ORM\Entity()
* #ORM\Table(name="third_party_entities")
*/
class ThirdPartyEntity
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #ORM\Column(name="aProperty", type="string", nullable=true)
*/
private $aProperty;
public function getId()
{
return $this->id;
}
public function getAProperty()
{
return $this->aProperty;
}
public function setAProperty($aProperty)
{
$this->aProperty = $aProperty;
return $this;
}
}
This question is cross-posted also on GitHub.
The solution was pretty simple: use another config method!
Practically, it is possible to mix configuration types and so, it is possible to use the annotations along with the yaml configuration.
Given this, it is sufficient to create a new config file in config/api_platform/third_party_entity.yaml.
In it put the configuration required to map the entity from the third party bundle:
resources:
App\Entity\MyEntity:
properties:
remote:
subresource:
resourceClass: 'Third\Party\Bundle\TheBundle\Entity\ThirdPartyEntity'
Third\Party\Bundle\TheBundle\Entity\ThirdPartyEntity:
This way it is possible to configure as subresource the entity from the third party bundle to which we don't have access with annotations.

Laravel with Linkedin API error - ServiceFactory::createService() must be an instance of OAuth\Common\Storage\TokenStorageInterface

I'm using Laravel to develop my website, and I integrated the linkedin login to it, it works fine for like a few months. then suddenly, last week i received an error. I didn't change any code that has something to do with Linkedin API. I'm suspecting whether it has something to do with Linkedin itself.
here's what the error looks like:
If you are using this library to integrate Linkedin to your laravel project, there might be an issue right now with the update. you can simply fix the error in OAuth.php by replacing it with this code:
<?php namespace Artdarek\OAuth;
/**
* #author Dariusz Prząda <artdarek#gmail.com>
* #copyright Copyright (c) 2013
* #license http://www.opensource.org/licenses/mit-license.html MIT License
*/
use \Config;
use \URL;
use \OAuth\ServiceFactory;
use \OAuth\Common\Consumer\Credentials;
class OAuth {
/**
* #var ServiceFactory
*/
private $_serviceFactory;
/**
* Storege name from config
*
* #var string
*/
private $_storage_name = 'Session';
/**
* Client ID from config
*
* #var string
*/
private $_client_id;
/**
* Client secret from config
*
* #var string
*/
private $_client_secret;
/**
* Scope from config
*
* #var array
*/
private $_scope = [];
/**
* Constructor
*
* #param ServiceFactory $serviceFactory - (Dependency injection) If not provided, a ServiceFactory instance will be constructed.
*/
public function __construct(ServiceFactory $serviceFactory = null)
{
if (null === $serviceFactory)
{
// Create the service factory
$serviceFactory = new ServiceFactory();
}
$this->_serviceFactory = $serviceFactory;
}
/**
* Detect config and set data from it
*
* #param string $service
*/
public function setConfig($service)
{
// if config/oauth-4-laravel.php exists use this one
if (Config::get('oauth-5-laravel.consumers') != null)
{
$this->_storage_name = Config::get('oauth-5-laravel.storage', 'Session');
$this->_client_id = Config::get("oauth-5-laravel.consumers.$service.client_id");
$this->_client_secret = Config::get("oauth-5-laravel.consumers.$service.client_secret");
$this->_scope = Config::get("oauth-5-laravel.consumers.$service.scope", []);
// esle try to find config in packages configs
}
else
{
$this->_storage_name = Config::get('oauth-5-laravel::storage', 'Session');
$this->_client_id = Config::get("oauth-5-laravel::consumers.$service.client_id");
$this->_client_secret = Config::get("oauth-5-laravel::consumers.$service.client_secret");
$this->_scope = Config::get("oauth-5-laravel::consumers.$service.scope", []);
}
}
/**
* Create storage instance
*
* #param string $storageName
*
* #return OAuth\Common\\Storage
*/
public function createStorageInstance($storageName)
{
$storageClass = "\\OAuth\\Common\\Storage\\$storageName";
$storage = new $storageClass();
return $storage;
}
/**
* Set the http client object
*
* #param string $httpClientName
*
* #return void
*/
public function setHttpClient($httpClientName)
{
$httpClientClass = "\\OAuth\\Common\\Http\\Client\\$httpClientName";
$this->_serviceFactory->setHttpClient(new $httpClientClass());
}
/**
* #param string $service
* #param string $url
* #param array $scope
*
* #return \OAuth\Common\Service\AbstractService
*/
public function consumer($service, $url = null, $scope = null)
{
// get config
$this->setConfig($service);
// get storage object
$storage = $this->createStorageInstance($this->_storage_name);
// create credentials object
$credentials = new Credentials(
$this->_client_id,
$this->_client_secret,
$url ? : URL::current()
);
// check if scopes were provided
if (is_null($scope))
{
// get scope from config (default to empty array)
$scope = $this->_scope;
}
// return the service consumer object
return $this->_serviceFactory->createService($service, $credentials, $storage, $scope);
}
}

Laravel Auth Custom Driver Error

FYI : I'm very new to Laravel and doing my best to learn it properly.
Working on an auth driver that uses a soap service to authenticate.
Error I get when trying to test with Auth::attempt()
Symfony \ Component \ Debug \ Exception \ FatalErrorException (E_COMPILE_ERROR)
Declaration of Project\Providers\AuthUserProvider::retrieveByToken() must be compatible with Illuminate\Auth\UserProviderInterface::retrieveByToken($identifier, $token)
Here is the driver...
<?php namespace Project\Providers;
use Illuminate\Auth\UserProviderInterface;
use Illuminate\Auth\GenericUser;
use Illuminate\Auth\UserInterface;
class AuthUserProvider implements UserProviderInterface {
/**
* External webservice for authentication
*/
private $webservice;
/**
* The user object.
*/
private $user;
/**
* Constructor
*
* #return void
*/
public function __construct(\Project\Webservice\AuthCheckApi $webservice)
{
$this->webservice = $webservice;
$this->user = null;
}
/**
* Retrieves a user by id
*
* #param int $identifier
* #return mixed null|array
*/
public function retrieveByID($identifier)
{
$this->user = is_null($this->user) ? $this->webservice->find($identifier) : $this->user;
return $this->user;
}
/**
* Tries to find a user based on the credentials passed.
*
* #param array $crendtials username|password
* #return mixed bool|UserInterface
*/
public function retrieveByCredentials(array $credentials)
{
if(!$user = $this->webservice->byusername($credentials['username'],$credentials['password'])) return false;
return new GenericUser($user);
}
/**
* Validates the credentials passed to the ones in webservice.
*
* #param UserInterface $user
* #param array $credentials
* #return bool
*/
public function validateCredentials(\Illuminate\Auth\UserInterface $user, array $credentials)
{
$validated = $this->webservice->validateCredentials($user,$credentials['username']);
return true;
}
/**
* Needed by Laravel 4.1.26 and above
*/
public function retrieveByToken()
{
return true;
}
/**
* Needed by Laravel 4.1.26 and above
*/
public function updateRememberToken()
{
return false;
}
}
Thanks for any help.
You are implementing the UserProviderInterface so you need to add the complete definition of all functions of the interface, here you are forgetting the arguments for the last two function
public function retrieveByToken($identifier, $token)
{
}
public function updateRememberToken($user, $token)
{
}

How to configure Hibernate Search to find words with accents

I need to implement a global search, on a website which I am implementing using Spring (4.0.2)/Hibernate(4.3.1)/MySQL. I have decided to use Hibernate Search(4.5.0) for this.
This seems to be working fine, but only when I do a search for an exact pattern.
Imagine I have the following text on an indexed field:
"A história do Capuchinho e do Lobo Mau"
1) If I search for "história" or "lobo mau", the query will retrieve the corresponding indexed entity, as I would have expected.
2) If I search for "historia" or "lobos maus" the search will not retrieve the entity.
As far as I have read, it should be possible to configure Hibernate Search to perform a much smarter search than this. Can anyone point me on the right direction to achieve this? See below key aspects of the implementation I executed. Thanks!
This is the "parent" indexed entity
#Entity
#Table(name="NEWS_HEADER")
#Indexed
public class NewsHeader implements Serializable {
static final long serialVersionUID = 20140301L;
private int id;
private String articleHeader;
private String language;
private Set<NewsParagraph> paragraphs = new HashSet<NewsParagraph>();
/**
* #return the id
*/
#Id
#Column(name="ID")
#GeneratedValue(strategy=GenerationType.AUTO)
#DocumentId
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the articleHeader
*/
#Column(name="ARTICLE_HEADER")
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
public String getArticleHeader() {
return articleHeader;
}
/**
* #param articleHeader the articleHeader to set
*/
public void setArticleHeader(String articleHeader) {
this.articleHeader = articleHeader;
}
/**
* #return the language
*/
#Column(name="LANGUAGE")
public String getLanguage() {
return language;
}
/**
* #param language the language to set
*/
public void setLanguage(String language) {
this.language = language;
}
/**
* #return the paragraphs
*/
#OneToMany(mappedBy="newsHeader", fetch=FetchType.EAGER, cascade=CascadeType.ALL)
#IndexedEmbedded
public Set<NewsParagraph> getParagraphs() {
return paragraphs;
}
// Other standard getters/setters go here
And this the IndexedEmbedded entity
#Entity
#Table(name="NEWS_PARAGRAPH")
public class NewsParagraph implements Serializable {
static final long serialVersionUID = 20140302L;
private int id;
private String content;
private NewsHeader newsHeader;
/**
* #return the id
*/
#Id
#Column(name="ID")
#GeneratedValue(strategy=GenerationType.AUTO)
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the content
*/
#Column(name="CONTENT")
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
public String getContent() {
return content;
}
// Other standard getters/setters go here
This is my search method, implemented on my SearchDAOImpl
public class SearchDAOImpl extends DAOBasics implements SearchDAO {
...
public List<NewsHeader> searchParagraph(String patternStr) {
Session session = null;
Transaction tx;
List<NewsHeader> result = null;
try {
session = sessionFactory.getCurrentSession();
FullTextSession fullTextSession = Search.getFullTextSession(session);
tx = fullTextSession.beginTransaction();
// Create native Lucene query using the query DSL
QueryBuilder queryBuilder = fullTextSession.getSearchFactory()
.buildQueryBuilder().forEntity(NewsHeader.class).get();
org.apache.lucene.search.Query luceneSearchQuery = queryBuilder
.keyword()
.onFields("articleHeader", "paragraphs.content")
.matching(patternStr)
.createQuery();
// Wrap Lucene query in a org.hibernate.Query
org.hibernate.Query hibernateQuery =
fullTextSession.createFullTextQuery(luceneSearchQuery, NewsHeader.class, NewsParagraph.class);
// Execute search
result = hibernateQuery.list();
} catch (Exception xcp) {
logger.error(xcp);
} finally {
if ((session != null) && (session.isOpen())) {
session.close();
}
}
return result;
}
...
}
This is what I have ended up doing, to resolve my problem.
Configure an AnalyzerDef at the entity level. Within it, use LowerCaseFilterFactory, ASCIIFoldingFilterFactory and SnowballPorterFilterFactory to achieve the type of filtering I needed.
#AnalyzerDef(name = "customAnalyzer",
tokenizer = #TokenizerDef(factory = StandardTokenizerFactory.class),
filters = {
#TokenFilterDef(factory = LowerCaseFilterFactory.class),
#TokenFilterDef(factory = ASCIIFoldingFilterFactory.class),
#TokenFilterDef(factory = SnowballPorterFilterFactory.class)
})
public class NewsHeader implements Serializable {
...
}
Add this notation for each of the fields I want indexed, either in the Parent entity or its IndexedEmbedded counterpart, to use the defined above analyzer.
#Field(index=Index.YES, store=Store.NO)
#Analyzer(definition = "customAnalyzer")
You will need to either re-index, or re-insert your entities, for the analyser to take effect.
You could configure, or you can use a standard language analyzer, such as PortugueseAnalyzer. I'd recommend starting from the existing analyzer, and creating you own if necessary, using it as a starting point for tweaking the filter chain.
You can set this in using the #Analyzer annotation for the field:
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO, analyzer = #Analyzer(impl = org.apache.lucene.analysis.pt.PortugueseAnalyzer.class))
Or you can set that analyzer as the default for the class, if you place an #analyzerannotation are the head of the class instead.
If you want to search accent character and also find same normal keyword in result then you must have to implement ASCIIFoldingFilterFactory class in analyzer like
#AnalyzerDef(name = "customAnalyzer",
tokenizer = #TokenizerDef(factory = StandardTokenizerFactory.class),
filters = {
#TokenFilterDef(factory = LowerCaseFilterFactory.class),
#TokenFilterDef(factory = ASCIIFoldingFilterFactory.class),
#TokenFilterDef(factory = StopFilterFactory.class, params = {
#Parameter(name="words", value= "com/ik/resource/stoplist.properties" ),
#Parameter(name="ignoreCase", value="true")
})
})
#Analyzer(definition = "customAnalyzer") apply on entity or fields

Symfony2-Doctrine: ManyToMany bi-directionnal relation

I've already search a lot befors asking, even the related topic Symfony2-Doctrine: ManyToMany relation is not saved to database
but still no answer.
I've got this two classes:
class Intervenant extends User
{
/**
* #ManyToMany(targetEntity="iMDEO\DISAASBundle\Entity\Domaine", inversedBy="intervenants", cascade={"persist","merge"})
*/
private $domaines;
/**
* Add domaines
*
* #param Domaine $domaines
*/
public function addDomaine(Domaine $domaines)
{
$this->domaines[] = $domaines;
}
/**
* Get domaines
*
* #return Doctrine\Common\Collections\Collection
*/
public function getDomaines()
{
return $this->domaines;
}
}
class Domaine
{
// ...
/**
* #ORM\ManyToMany(targetEntity="Intervenant", mappedBy="domaines", cascade={"persist","merge"})
*
*/
private $intervenants;
/**
* Add intervenants
*
* #param Intervenant $intervenants
*/
public function addIntervenant(Intervenant $intervenants)
{
$intervenants->addDomaine($this);
$this->intervenants[] = $intervenants;
}
/**
* Get intervenants
*
* #return Doctrine\Common\Collections\Collection
*/
public function getIntervenants()
{
return $this->intervenants;
}
}
When I save an Intervenant, everthing is OK.
But when i save the inverse side Domaine, the changes are not persisted.
Reading Symfony's doc and topics everywhere, I can't find any solution to get a bi-directionnal relation between my two entities.
Here's part of my DomaineController:
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('myBundle:Domaine')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Domaine entity.');
}
$editForm = $this->createForm(new DomaineType(), $entity);
$deleteForm = $this->createDeleteForm($id);
$request = $this->getRequest();
$editForm->bindRequest($request);
if ($editForm->isValid()) {
$em->persist($entity);
$em->flush();
return $this->indexAction();
}
// ...
My purpose is that when I create/edit an Intervenant, I can choose related Domaine.
And when I create/edit a Domaine, I link every Intervenants in it.
Could you please help me?