i'm needing your help.
i have 3 tables on my database running on postgresql. they are exactly the same structure. so i thought if i could mapp them in one entity.
i try this:
#Entity
#Table(name = "stock_tierra")
#SecondaryTables({
#SecondaryTable(name = "stock_bebelandia"),
#SecondaryTable(name = "stock_libertador")
})
public class Stock implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_stock", unique = true, nullable = false)
private int idStock;
#Column(name = "cantidad", nullable = false)
private int cantidad;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "id_producto", nullable = false)
private Producto idProducto;
#Column(name = "estado", nullable = false)
private boolean estado;
#Column(name = "usuario_creacion", nullable = false)
private int usuarioCreacion;
#Column(name = "usuario_modificacion")
private Integer usuarioModificacion;
#Temporal(TemporalType.DATE)
#Column(name = "fecha_creacion", nullable = false, length = 13)
private Date fechaCreacion;
#Temporal(TemporalType.DATE)
#Column(name = "fecha_modificacion", length = 13)
private Date fechaModificacion;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "id_sucursal", nullable = false)
private Sucursal idSucursal;
but when i try to look in to one table i only get data from the first stock_tierra
String stockSucursal = null;
switch (sucursal) {
case 1:
stockSucursal = "stock_tierra";
break;
case 2:
stockSucursal = "stock_bebelandia";
break;
case 3:
stockSucursal = "stock_libertador";
break;
}
Criteria criteria = getSession().createCriteria(Stock.class, stockSucursal);
criteria.add(Restrictions.eq("estado", true));
criteria.addOrder(Order.asc("idStock"));
List<Stock> list = criteria.list();
return list;
some idea what i'm doing wrong?
#SecondaryTables is used to denote one entity being spread over multiple tables in terms of columns, not as a union.
The only thing I can think of right now is using a view which does a union over all the tables, but I am not sure whether postgres can handle writable views, or how you declare them (if you even need a write interface.)
Related
I have a table with n x n relationship. That means i have a code that is repeated with only a "brand" column being different between them. The code is not the ID.
I need to have one distinct class that contains all repeatable values and with a list that has all the unique brand column values.I cannot show most of the code samples because of my company security policies. But the entity below is a mock of what i'm seeking.
`
#Entity
#Table(name = "Table")
public class Teste {
#Column(name = "CODE", insertable = false, updatable = false)
private String code;
#Column(name = "NAME")
private String name;
#Column(name = "BRAND")
private String brand;
#OneToMany(cascade = CascadeType.ALL)
#JoinTable(name = "BRAND", joinColumns = { #JoinColumn(name = "CODE"), #JoinColumn(name = "BRAND")})
private Set<Model> brands = new HashSet<>();
#Column(name = "UPDATE_DATE")
private Date update_date;
#Column(name = "EDITOR")
private String editor;
#Id
#Column(name = "ID")
private int id;
}
`
I have to join two tables with ManyToOne relationship using JPA.
TABLE 1 -> manF
#Entity
#Table(name = "manf")
public class ManF {
#EmbeddedId
private ManFCompositeKey manFCompositeKey;
#Column(name = "name", length = 10)
private String manFName;
#Column(name = "desc", length = 150)
private String manFDesc;
}
#Embeddable
public class ManFCompositeKey {
#Column(name = "man_code", length = 20, nullable = false)
private String manCode;
#Column(name = "update_time", nullable = false)
private Date updTime;
}
TABLE 2 -> products
#Entity
#Table(name = "products")
public class Prod {
#EmbeddedId
private ProdCompositeKey prodCompositeKey;
#Column(name = "name", length = 10)
private String prodName;
#Column(name = "prod_desc", length = 150)
private String prodDesc;
// -> JoinColumn here.
#Column(name = "man_code", length = 20, nullable = false)
private String manCode;
}
#Embeddable
public class ProdCompositeKey {
#Column(name = "prod_code", length = 20, nullable = false)
private String prodCode;
#Column(name = "update_time", nullable = false)
private Date updTime;
}
Now, manF(Table 1) can have many products(Table 2). Thus, for each row in product table, there can be same manFCode.
I intend to establish a join b/w T1 and T2 such that manCode column in products behaves as the FK for this table referenceing man_code of Table 1.
Below is the join condition I wrote:
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumns({
#JoinColumn(name = "man_code", referencedColumnName = "man_code")
})
#Column(name = "man_code", length = 20, nullable = false)
private ManF manF;
This should make sense(I thought), but threw an error, stating: ManF not mapped to a single property.
Now I can do this:
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumns({
#JoinColumn(name = "man_code", referencedColumnName = "man_code")
#JoinColumn(name = "update_time", referencedColumnName = "update_time")
})
#Column(name = "man_code", length = 20, nullable = false)
private ManF manF;
But then I would be keeping a FK reference on the time, on which a ManF was inserted.
I need to know how can I join the two tables here such that I can create a FK reference on the man_code of ManF table and the man_code in the product (child) table.
You can use hibernate native query and write the join condition. If that is not a option I would particularly change the embeddedId on Manf to a regular id and create a constraint in your db, to maintain integrity an use a regular joincolumn condition. Like this:
SQL: ALTER TABLE 'manf' ADD UNIQUE 'UNIQUE_CONSTRAINT'('man_code', 'update_time');
#Entity
#Table(name = "manf")
public class ManF {
#Id
#SequenceGenerator(name = "SEQUENCE_NAME", sequenceName = "SEQUENCE_NAME", allocationSize = 1, initialValue = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_NAME")
#Column(name = "man_code", length = 20, nullable = false)
private String manCode;
#Column(name = "update_time", nullable = false)
private Date updTime;
#Column(name = "name", length = 10)
private String manFName;
#Column(name = "desc", length = 150)
private String manFDesc;
}
#Entity
#Table(name = "products")
public class Prod {
#EmbeddedId
private ProdCompositeKey prodCompositeKey;
#Column(name = "name", length = 10)
private String prodName;
#Column(name = "prod_desc", length = 150)
private String prodDesc;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "man_code")
private ManF manF;
}
This is what I have done, to achieve this. May be a hack.
I have put the man_code from from Table 1 (ManF), in the main class (it stays is the Embeddable as well). But in the ManF class I did something like this:
#Entity
#Table(name = "manf")
public class ManF {
#EmbeddedId
private ManFCompositeKey manFCompositeKey;
*#Column(name = "man_code", insertable = false, updatable= false)
private String manCode;*
#Column(name = "name", length = 10)
private String manFName;
#Column(name = "desc", length = 150)
private String manFDesc;
}
#Embeddable
public class ManFCompositeKey {
#Column(name = "man_code", length = 20, nullable = false)
private String manCode;
#Column(name = "update_time", nullable = false)
private Date updTime;
}
On the other hand, I have changed my Table 2 as follows:
#Entity
#Table(name = "products")
public class Prod {
#EmbeddedId
private ProdCompositeKey prodCompositeKey;
#Column(name = "name", length = 10)
private String prodName;
#Column(name = "prod_desc", length = 150)
private String prodDesc;
*#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumns({
#JoinColumn(name = "man_code", referencedColumnName =
"man_code")})
private ManF manF;*
*#Column(name = "man_code", insertable = false, updatable = false)
private String manCode;*
#Column(name = "man_code", length = 20, nullable = false)
private String manCode;
}
#Embeddable
public class ProdCompositeKey {
#Column(name = "prod_code", length = 20, nullable = false)
private String prodCode;
#Column(name = "update_time", nullable = false)
private Date updTime;
}
This is somehow working, but I have had to add a new variable in the Child table (here: manCode with insertable and updatabale as false)
I am not sure if this is the correct approach. Please, let me know if someone has a better and elegant idea to approach this issue.
A Foreign key refering br.com.copagaz.inova.mobile.persistencia.entidade.viagem.nf.NFeProtocolo from br.com.copagaz.inova.mobile.persistencia.entidade.viagem.nf.NfCabeca has the wrong number of column. should be 2
My problem is in one column reference, if i remove #ManyToOne and #JoinColumn(name = "protocolo"), the system works but the selects does not.
i tried to use hibernate.hbm2ddl.auto to auto create the FKs but with no success.
I think the nfe_operacao use a composed PK, and nf_cabeca reference's ii, but did not work.
Any one could help?
#Entity
#Table(name = "nf_cabeca", schema = "mobile", uniqueConstraints =
{#UniqueConstraint(columnNames =
{"NUMERO_FILIAL","serie_nota","numero_nota"})})
public class NfCabeca implements java.io.Serializable {
private static final long serialVersionUID = -921687831233770627L;
#Id
#SequenceGenerator(name = "nf_cabeca_sequencial_seq", sequenceName = "nf_cabeca_sequencial_seq", schema = "mobile", allocationSize = 1, initialValue = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "nf_cabeca_sequencial_seq")
#Column(name = "sequencial", insertable = false, updatable = false)
private long sequencial;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "data_hora", nullable = false, length = 29)
private Date dataHora;
#Column(name = "valor_total", nullable = false, precision = 17, scale = 17)
private Double valorTotal;
#Column(name = "cancelada")
private Integer cancelada;
#Temporal(TemporalType.DATE)
#Column(name = "data_vencimento", length = 13)
private Date dataVencimento;
#Column(name = "boleto", length = 17)
private String boleto;
#ManyToOne
#JoinColumn(name = "protocolo")
private NFeProtocolo protocolo;
#Column(name = "chave")
private String chave;
#Column(name = "status_nf")
private Integer statusNf;
#Column(name = "status_danfe")
private Integer statusDanfe;
#Column(name = "modelo", length = 3)
private String modelo;
#Column(name = "reconciliada")
private boolean reconciliada = false;
#OneToMany(mappedBy = "nfCabeca", cascade = CascadeType.MERGE)
private List<NfObservacao> nfObservacao;
#OneToMany(mappedBy = "nfCabeca", cascade = CascadeType.ALL)
private List<NfItens> nfItens;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "nf_cabeca")
private List<NFeProtocolo> protocolos = new ArrayList<NFeProtocolo>();
}
This references this table:
#Entity
#IdClass(NFeProtocoloId.class)
#Table(name = "nfe_protocolo", schema = "mobile")
public class NFeProtocolo implements Serializable {
private static final long serialVersionUID = 2092981840170296102L;
#Id
#Column(name = "nf_cabeca", length = 100, insertable = false, updatable = false)
private long nf_cabeca_id;
#Id
#Column(name = "protocolo", length = 100)
private String protocolo;
#Column(name = "operacao", length = 15, nullable = false)
#Enumerated(EnumType.STRING)
private NFeProtocoloOperacao operacao;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "data_hora", length = 29, nullable = false)
private Date dataHora;
#Column(name = "status", length = 10)
private String status;
}
I think the problem is that your #ManyToOne mapping is not correctly declared. As the the entity NFeProtocolo has a composite primary key, you should use #JoinColumns annotation that consists of an array of #JoinColumn annotations:
#ManyToOne
#JoinColumns({#JoinColumn(name = "nf_cabeca_id", referncedColumnName="nf_cabeca_id"),
#JoinColumn(name= "protocolo", referencedColumnName="protocolo")})
private NFeProtocolo protocolo;
You can choose an appropriate name as a foreign key column name.
A Foreign key refering br.com.copagaz.inova.mobile.persistencia.entidade.viagem.nf.NFeProtocolo from br.com.copagaz.inova.mobile.persistencia.entidade.viagem.nf.NfCabeca has the wrong number of column. should be 2
Your problem is simple: Your Entity NFeProtocolo has a composite Id with two columns:
public class NFeProtocolo implements Serializable {
#Id
#Column(name = "nf_cabeca", length = 100, insertable = false, updatable = false)
private long nf_cabeca_id;
#Id
#Column(name = "protocolo", length = 100)
private String protocolo;
But your class NfCabeca is referencing it through only one column:
public class NfCabeca implements java.io.Serializable {
#ManyToOne
#JoinColumn(name = "protocolo")
private NFeProtocolo protocolo;
The solution:
A composite primary key is usually made up of two or more primitive or JDK object types.
As you have a composite key, you should use an Embeddable key, there are many examples about it like this, this and this.
I am very new to JPA and have the following entities defined
public class CustomerOrders {
#Column(name = "CUSTOMER_ID", nullable = false)
private Long customerId;
#OneToMany(cascade = {CascadeType.ALL}, orphanRemoval = true)
#JoinColumn(name = "ORDER_ID", nullable = false)
private List<Order> orders;
}
public class Order {
#Column(name = "ORDER_ID", nullable = false)
private Long orderId;
#Column(name = "AMOUNT", precision = 16, scale = 2, nullable = false)
private BigDecimal orderAmount;
#Column(name ="AWARD_FULFILLED_INDIC", nullable = false)
private Boolean awardFulIndicator;
}
Given the above, how would I write a JPA query against the CustomerOrders entity, that when passed the customer id as a parameter, it would return those CustomerOrders having at least one Order with an amount of greater than $10 positive amount and whose AWARD_FULFILLED_INDIC is true?
Thank you in advance.
I'd try this:
SELECT * FROM CustomerOrders c INNER JOIN c.orders o
WHERE c.customerId = :cId AND o.awardFulIndic = true
HAVING MAX(o.orderAmount) >= 10.00;
#MawrCoffeePls 's solution worked
Well i have this problem
These are my tables
this is my code for "Compra"
#Entity
#Table(name = "compra")
public class Compra implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "codigo", unique = true, nullable = false)
private int codigo;
#ManyToOne
#JoinColumn(name = "codProveedor", nullable = false)
private Proveedor proveedor;
#Column(name = "tipoComprobante", nullable = false)
private String tipoComprobante;
#Temporal(TemporalType.DATE)
#Column(name = "fechaFactura", nullable = false)
private Date fechaFactura;
#Temporal(TemporalType.DATE)
#Column(name = "fechaLlegada", nullable = false)
private Date fechaLlegada;
#Column(name = "serie", nullable = false)
private String serie;
#Column(name = "numero", nullable = false)
private int numero;
#Column(name = "importe", nullable = false)
private double importe;
#Column(name = "vigencia", nullable = false)
private boolean vigencia = true;
#ElementCollection
private List<DetalleCompra> lstDetalle = new ArrayList<DetalleCompra>();
// getters and setters ...
And this is my code for "DetalleCompra"
#Entity
#Table(name = "detalleCompra")
public class DetalleCompra implements Serializable {
#Id
#GeneratedValue(generator = "gen")
#GenericGenerator(name = "gen", strategy = "foreign", parameters = #Parameter(name = "property", value = "compra"))
#Column(name = "codCompra", nullable = false)
private int codCompra;
#ManyToOne
#JoinColumn(name = "codPresentacion", nullable = false)
private Presentacion presentacion;
#Column(name = "imei", nullable = false)
private String imei;
#Column(name = "simcard", nullable = false)
private String simcard;
getters and setters ...
Well everything looks fine, but when i want to save i have this problem
org.hibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing: DetalleCompra
well it is clear because when i want to save Compra and DetalleCompra, the second table expect the fk value
public void registrar(Compra compra) {
try {
session = HibernateUtil.getSessionFactory().openSession();
trans = session.beginTransaction();
session.save(compra);
trans.commit();
} catch (Exception e) {
trans.rollback();
throw e;
} finally {
session.close();
}
}
Well the pk of table "compra" is generated well but for the other table does not recognized this value autogenerated, why?, how can i solve that?
#ElementCollection
Defines a collection of instances of a basic type or embeddable class.
Must be specified if the collection is to be mapped by means of a
collection table.
You use wrong annotation to represent relation. There is one to many relation between Compra and DetalleCompra.
You should change #ElementCollection annotation to #OneToMany. Do not forget to specify join columns #JoinColumn(name="codCompra"). I assume that Presentacion is properly mapped.
See also
Unidirectional Mapping vs. Bidirectional Mapping
mappedBy attribute
#OneToMany annotation
#ElementCollection annotation