http://docs.phalconphp.com/en/0.6.0/reference/phql.html
Usage Example
To better explain how PHQL works consider the following example. We have two models “Cars” and “Brands”:
<?php
class Cars extends Phalcon\Mvc\Model
{
public $id;
public $name;
public $brand_id;
public $price;
public $year;
public $style;
/**
* This model is mapped to the table sample_cars
*/
public function getSource()
{
return 'sample_cars';
}
/**
* A car only has a Brand, but a Brand have many Cars
*/
public function initialize()
{
$this->belongsTo('brand_id', 'Brands', 'id');
}
}
And every Car has a Brand, so a Brand has many Cars:
<?php
class Brands extends Phalcon\Mvc\Model
{
public $id;
public $name;
/**
* The model Brands is mapped to the "sample_brands" table
*/
public function getSource()
{
return 'sample_brands';
}
/**
* A Brand can have many Cars
*/
public function initialize()
{
$this->hasMany('id', 'Brands', 'brand_id'); // here
}
}
You are correct. The relationship should have been hasMany on Cars not Brands. The corrected example is below
http://docs.phalconphp.com/en/latest/reference/phql.html
<?php
class Cars extends Phalcon\Mvc\Model
{
public $id;
public $name;
public $brand_id;
public $price;
public $year;
public $style;
/**
* This model is mapped to the table sample_cars
*/
public function getSource()
{
return 'sample_cars';
}
/**
* A car only has a Brand, but a Brand have many Cars
*/
public function initialize()
{
$this->belongsTo('brand_id', 'Brands', 'id');
}
}
And every Car has a Brand, so a Brand has many Cars:
<?php
class Brands extends Phalcon\Mvc\Model
{
public $id;
public $name;
/**
* The model Brands is mapped to the "sample_brands" table
*/
public function getSource()
{
return 'sample_brands';
}
/**
* A Brand can have many Cars
*/
public function initialize()
{
$this->hasMany('id', 'Cars', 'brand_id');
}
}
Related
I have that nativeQuery Query in my Repository.
#Query(value = "Select * from Company a left join Industry b on a.industry_id=b.id", nativeQuery = true)
public List < Company > findJoin();
But when i run the Page I have that error
could not extract ResultSet; SQL [n/a]; nested exception is
org.hibernate.exception.SQLGrammarException: could not extract
ResultSet
Company
#Entity
public class Company {
private long id;
private String name;
private String website;
private String about;
private String city;
private int location;
private int industry_id;
/**
* #return the industry_id
*/
public int getIndustry_id() {
return industry_id;
}
/**
* #param industry_id the industry_id to set
*/
public void setIndustry_id(int industry_id) {
this.industry_id = industry_id;
}
private int numbere;
private Industry industry;
/**
* #return the id
*/
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public long getId() {
return id;
}
/**
* #param id
* the id to set
*/
public void setId(long id) {
this.id = id;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name
* the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* #return the website
*/
public String getWebsite() {
return website;
}
/**
* #param website
* the website to set
*/
public void setWebsite(String website) {
this.website = website;
}
/**
* #return the about
*/
public String getAbout() {
return about;
}
/**
* #param about
* the about to set
*/
public void setAbout(String about) {
this.about = about;
}
/**
* #return the city
*/
public String getCity() {
return city;
}
/**
* #param city
* the city to set
*/
public void setCity(String city) {
this.city = city;
}
/**
* #return the location
*/
public int getLocation() {
return location;
}
/**
* #param location
* the location to set
*/
public void setLocation(int location) {
this.location = location;
}
/**
* #return the industry_id
*/
/**
* #param industry_id
* the industry_id to set
*/
/**
* #return the numbere
*/
public int getNumbere() {
return numbere;
}
/**
* #param numbere
* the numbere to set
*/
public void setNumbere(int numbere) {
this.numbere = numbere;
}
/**
* #return the industry
*/
#ManyToOne
#JoinColumn(name = "industry_id",insertable = false, updatable =
false)
public Industry getIndustry() {
return industry;
}
/**
* #param industry
* the industry to set
*/
public void setIndustry(Industry industry) {
this.industry = industry;
}
// private byte[] logo;
}
Industry
#Entity
public class Industry {
#Column(name="ides")
private long id;
#Column(name="namens")
private String name;
private Set<Company> company;
/**
* #return the id
*/
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public long getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(long id) {
this.id = id;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* #return the company
*/
#OneToMany(mappedBy = "industry", cascade = CascadeType.ALL)
public Set<Company> getCompany() {
return company;
}
/**
* #param company the company to set
*/
public void setCompany(Set<Company> company) {
this.company = company;
}
}
Can somehone hlp me please. Or how to convert this nativeQuery to Hibernate sql? Thanks
Try this in your JPA repository
#Query("Select c from Company c where c.industry.id = :id")
List<Company> findJoin(#Param("id") long id);
PS: Haven't tested this but it should work given that your mapping is correct.
Following this link
I would like to use OneToMany instead ManyToMany annotation, having middle class with composite key in it using Ebean. I have this error:
java.lang.RuntimeException: Error reading annotations for models.SoftwareTagPk
This is my SoftwareTagPk class:
#Embeddable
public class SoftwareTagPk implements Serializable {
#ManyToOne
private Tag tag;
#ManyToOne
private Software software;
...
}
And SoftwareTag class:
#Entity
public class SoftwareTag extends Model {
#EmbeddedId
private SoftwareTagPk pk = new SoftwareTagPk();
#Transient
public Tag getTag() {
return pk.getTag();
}
public void setTag(Tag aTag) {
pk.setTag(aTag);
}
#Transient
public Software getSoftware() {
return pk.getSoftware();
}
public void setSoftware(Software aSoftware) {
pk.setSoftware(aSoftware);
}
}
Also in logs:
Error with association to [class models.Tag] from
[models.SoftwareTagPk.tag]. Is class models.Tag registered?
How to fix it?
To make this code work you have to do:
In your SoftwareTagPk class put only id's of Tag and Software
Move #ManyToOne relations to SoftwareTag class
Add #JoinColumn annotations with attributes updatable and insertable set to false.
Override setters setTag and setSoftware in SoftwareTag class. In these setters you will rewrite id's to composite key.
Main idea of this solution is that SoftwareTag has composite key and #ManyToOne relations and they are mapped to the same collumns.
This is the code:
Tag.java
#Entity
public class Tag extends Model {
#Id
private Integer id;
#OneToMany(mappedBy="tag")
public List<SoftwareTag> softwareTags;
public Integer getId() {
return id;
}
public void setId(Integer aId) {
id=aId;
}
public static Finder<Integer,Tag> find = new Finder<Integer,Tag>(
Integer.class, Tag.class
);
}
Software.java
#Entity
public class Software extends Model {
#Id
private Integer id;
#OneToMany(mappedBy="software")
public List<SoftwareTag> softwareTags;
public Integer getId() {
return id;
}
public void setId(Integer aId) {
id=aId;
}
}
SoftwareTag.java
#Entity
public class SoftwareTag extends Model {
SoftwareTag() {
pk = new SoftwareTagPk();
}
#EmbeddedId
private SoftwareTagPk pk = new SoftwareTagPk();
#ManyToOne
#JoinColumn(name = "tag_id", insertable = false, updatable = false)
private Tag tag;
#ManyToOne
#JoinColumn(name = "software_id", insertable = false, updatable = false)
private Software software;
public Tag getTag() {
return tag;
}
public void setTag(Tag aTag) {
tag = aTag;
pk.tag_id = aTag.getId();
}
public Software getSoftware() {
return software;
}
public void setSoftware(Software aSoftware) {
software = aSoftware;
pk.software_id = aSoftware.getId();
}
}
SoftwareTagPk.java
#Embeddable
public class SoftwareTagPk implements Serializable {
public Integer tag_id;
public Integer software_id;
#Override
public int hashCode() {
return tag_id + software_id;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
SoftwareTagPk pk = (SoftwareTagPk)obj;
if(pk == null)
return false;
if (pk.tag_id.equals(tag_id) && pk.software_id.equals(software_id)) {
return true;
}
return false;
}
}
Hi I'm used to have the following entity
public class Foo
{
private IList<Bar> _bars;
public IEnumerable<Bar> Bars { get { return bars; } }
public void Add(Bar bar)
{
/* Validation logic here */
_bars.Add(bar);
}
}
I'm suspecting this won't work with RavenDb or am I'm wrong?
Can I keep my collection with Bars protected from outside manipulating (in other words not allowing foo.Bars.Add(bar);)
I found the solution to use two properties.
public IEnumerable Bars { get { return InnerBars; } }
private List InnerBars { get; set; }}
A private setter on an automatic property is the easiest and most readable way without doing anything special.
public class Foo
{
public IEnumerable<Bar> Bars { get; private set; }
public void Add(Bar bar)
{
Bars.Add(bar);
}
}
Another way would be with attributes:
// pick one or the other
using Newtonsoft.Json // on 1.0
using Raven.Imports.Newtonsoft.Json // on 2.0
...
public class Foo
{
[JsonProperty(PropertyName = "Bars")]
private IList<Bar> _bars;
[JsonIgnore]
public IEnumerable<Bar> Bars { get { return bars; } }
public void Add(Bar bar)
{
_bars.Add(bar);
}
}
I have a question, that is "category class" contains many product class. but now, i have a CategoryService class that will implement find IList at the same sutiation every category only contain the top n of products, not all of products, what should i do? Give me a choice,thanks!
the code list:
public class category
{
public int Id{get;set;}
public int Categoryname{get;set;}
public IList<Product> Products{get;set;}
}
public class Product
{
public int Id{get;set;}
public string ProductName{get;set;}
public Category Category{get;set;}
etc...
}
then have a domain service:
public class CategoryService
{
private ICategoryRepository categoryRepository;
public CategoryService(ICategoryRepository categoryRepository)
{
this.categoryRepository=categoryRepository;
}
public IList<Category> FindAll()
{
IList<Category> categories;
categories=categoryRepository.FindAll();
//and now i need categoryRepository find all category ,and every category contains top n product, what should i do;
return categories;
}
}
var count = // it's your top
session.QueryOver<Category>
.Fetch(category => category.Product).Eager
.Take(count)
.TransformUsing(Transformers.DistinctRootEntity)
.List();
I have this mapping:
public sealed class EntityMap : ClassMap<Entity>
{
public EntityMap ()
{
...
Component(entity => entity.StateHistory,
m => m.HasMany<HistoryItem<EntityState>>
(Reveal.Property<EntityStateHistory>("Items"))
.Table("EntityStateHistory")
.KeyColumn("IDEntity")
.Component
( m2 =>
{
m2.Map(esh => esh.Item, "State")
.CustomType(typeof(EntityState)).Not.Nullable();
m2.Map(esh=> esh.Date, "TransitionDate").Not.Nullable();
}
)
.Cascade.AllDeleteOrphan());
...
}
}
I want to make a query where i get a specific date (TransitionDate) in an EntityStateHistory entry.
If it was possible it would be something like this:
"select e from Entity e where e.StateHistory.Items.Date = :date"
but i can't do this, i don't know how i can access an History record date, knowing that History is a component that has itself a collection of components, and i need to access one of the properties of those components in the collection.
The object model is something like this:
public class Entity
{
private int ID {get; set;}
etc
...
public virtual EntityStateHistory StateHistory{ get; private set; }
}
public class EntityStateHistory: History<EntityState>
{
//some wraped properties and methods
public IList<HistoryItem<EntityState>> StateRecords
{
get { return base.Items;}
}
public bool ContainsStateRecord(EstadoOT state)
{
return base.Items.Count(i => i.Item.Equals(state)) > 0;
}
etc ...
}
public class History<T>
{
protected virtual IList<HistoryItem<T>> Items { get; private set; }
public History()
{
Items = new List<HistoryItem<T>>();
}
protected virtual HistoryItem<T> AddHistoryItem(DateTime data, T item)
{
...
}
}
public class ItemHistory<T>
{
#region NHibernate
private int ID { get; set; }
#endregion
public virtual DateTime Date { get; private set; }
public virtual T Item { get; private set; }
...
}
I know i will probably have to change the mapping for entity, and create a map for EntityStateHistory, but i would like to avoid that, because that means one more table. The way i have it is the most canonical mapping because has no need to map HistoryItem or EntityStateHistory, that means i only use one table to map EntityStateHistory:
Table EntitiStateHistory:
-IDEntity
-TransitionDate
-State
So is it possible with the current mapping to query the database for a Entity that has a specific history record date?
Thanks
It was so easy...
The problem was in the path:
"select e from Entity e where e.StateHistory.Items.Date = :date"
if i do this:
"select e from Entity e join e.StateHistory.Items i where i.Date = :date"
it works