I have a database with several different, but related tables:
class AccountInfo {
string id;
string name;
string email;
}
class ExtraInfo {
string id;
string proxy;
}
class UserInfo {
AccountInfo account;
ExtraInfo extra;
}
public class MyDbContext : DbContext {
public DbSet<AccountInfo> AccountInfo { get; set; }
public DbSet<ExtraInfo> ExtraInfo { get; set; }
}
public class ExtraInfoController : ODataController
{
private readonly DS2DbContext _context;
private readonly ILogger<UserInfoController> _logger;
public ExtraInfoController(DS2DbContext context) {
_context = context;
}
[EnableQuery(PageSize = 15)]
public IQueryable<UserInfo> Get() {
IQueryable<UserInfo> query =
from a in _context.AccountInfo
from x in _context.ExtraInfo
where (a.id == x.id)
select new UserInfo() { account = a, extra = x };
return query;
}
The query in ExtraInfoController.Get() works, but the result cannot be transferred back to the calling code, because the DbSet is declared for type ExtraInfo and I guess because of the way Blazor mangles all the pseudo code passed to it into working code, so it expects the return type to be IQueryable and not IQeryable.
I am new to EF core, so I don't know how to create a controller that is not directly related to a db table that would do the desired join and return an IQueryable without there being a UserInfo table in the db.
How to write OneToMany relation in jpa entity class using javafx listproperty
I tried this:
private final ListProperty<Bill> bills = new SimpleListProperty<>();
#OneToMany(targetEntity = Bill.class, mappedBy = "invoice")
public ObservableList getBills() {
return bills.get();
}
public void setBills(ObservableList value) {
bills.set(value);
}
public ListProperty billsProperty() {
return bills;
}
getting error : " oneTomany attribute type should be [java.util.colletion, java.util.List]
Simply use List rather than ObservableList from the getter and setter functions.
private final ListProperty<Bill> bills = new SimpleListProperty<>();
#OneToMany(targetEntity = Bill.class, mappedBy = "invoice")
public List getBills() {
return bills.get();
}
public void setBills(List value) {
bills.set(FXCollections.observableArrayList(value));
}
public ListProperty billsProperty() {
return bills;
}
I have a jpa query that should return 4 rows, and it does return 4 rows, but only the first 2 rows of the result are ok, the next 2 are the first row repeated. And no, the first row is not repeated in the database.
this is my query:
public static List<DetalleProcesosEntity> getALLbyid(int id_proceso){
Query q = entityManager.createQuery("select a from DetalleProcesosEntity a where a.idProceso=:id_proceso");
q.setParameter("id_proceso", id_proceso);
List<DetalleProcesosEntity>resultado=q.getResultList();
List<DetalleProcesosEntity>result=new ArrayList<DetalleProcesosEntity>(resultado);
return result;
}
what im doing is:
from a view called "procesos" wich contains a table i click in any of the "procesos" in the table and i go to its details (passing the "proceso" ID as a parameter):
this is the details backing bean:
#ManagedBean(name = "det_procesos")
#ViewScoped
public class DetalleProcesosBean {
private int idProceso;
private List<DetalleProcesosEntity>detalles;
#PostConstruct
public void init(){
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
//Obtener parametros del request
Map<String, String> parameterMap = externalContext.getRequestParameterMap();
idProceso = Integer.parseInt(parameterMap.get("id_proc"));
detalles= Procesos.getALLbyid(idProceso);
}
public List<DetalleProcesosEntity> getDetalles() {
return detalles;
}
public void setDetalles(List<DetalleProcesosEntity> detalles) {
this.detalles = detalles;
}
public int getIdProceso() {
return idProceso;
}
public void setIdProceso(int idProceso) {
this.idProceso = idProceso;
}
}
if i use distinct in the query it does not make any difference, i just get 2 rows and im sure in the database there are 4 rows with the same "id proceso" and different values.
I solved it.. it was because i was working with views and i did not setted a proper ID to one of them (i had to add #Id to one of attributes of the entity)
I'm using EclipseLink to run some Native SQL. I need to return the data into a POJO. I followed the instructions at EclipseLink Docs, but I receive the error Missing descriptor for [Class]
The query columns have been named to match the member variables of the POJO. Do I need to do some additional mapping?
POJO:
public class AnnouncementRecipientsFlattenedDTO {
private BigDecimal announcementId;
private String recipientAddress;
private String type;
public AnnouncementRecipientsFlattenedDTO() {
super();
}
public AnnouncementRecipientsFlattenedDTO(BigDecimal announcementId, String recipientAddress, String type) {
super();
this.announcementId = announcementId;
this.recipientAddress = recipientAddress;
this.type = type;
}
... Getters/Setters
Entity Manager call:
public List<AnnouncementRecipientsFlattenedDTO> getNormalizedRecipientsForAnnouncement(int announcementId) {
Query query = em.createNamedQuery(AnnouncementDeliveryLog.FIND_NORMALIZED_RECIPIENTS_FOR_ANNOUNCEMENT, AnnouncementRecipientsFlattenedDTO.class);
query.setParameter(1, announcementId);
return query.getResultList();
}
I found out you can put the results of a Native Query execution into a List of Arrays that hold Objects. Then one can iterate over the list and Array elements and build the desired Entity objects.
List<Object[]> rawResultList;
Query query =
em.createNamedQuery(AnnouncementDeliveryLog.FIND_NORMALIZED_RECIPIENTS_FOR_ANNOUNCEMENT);
rawResultList = query.getResultList();
for (Object[] resultElement : rawResultList) {
AnnouncementDeliveryLog adl = new AnnouncementDeliveryLog(getAnnouncementById(announcementId), (String)resultElement[1], (String)resultElement[2], "TO_SEND");
persistAnnouncementDeliveryLog(adl);
}
You can only use native SQL queries with a class if the class is mapped. You need to define the AnnouncementRecipientsFlattenedDTO class as an #Entity.
Otherwise just create the native query with only the SQL and get an array of the data back and construct your DTO yourself using the data.
Old question but may be following solution will help someone else.
Suppose you want to return a list of columns, data type and data length for a given table in Oracle. I have written below a native sample query for this:
private static final String TABLE_COLUMNS = "select utc.COLUMN_NAME, utc.DATA_TYPE, utc.DATA_LENGTH "
+ "from user_tab_columns utc "
+ "where utc.table_name = ? "
+ "order by utc.column_name asc";
Now the requirement is to construct a list of POJO from the result of above query.
Define TableColumn entity class as below:
#Entity
public class TableColumn implements Serializable {
#Id
#Column(name = "COLUMN_NAME")
private String columnName;
#Column(name = "DATA_TYPE")
private String dataType;
#Column(name = "DATA_LENGTH")
private int dataLength;
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public int getDataLength() {
return dataLength;
}
public void setDataLength(int dataLength) {
this.dataLength = dataLength;
}
public TableColumn(String columnName, String dataType, int dataLength) {
this.columnName = columnName;
this.dataType = dataType;
this.dataLength = dataLength;
}
public TableColumn(String columnName) {
this.columnName = columnName;
}
public TableColumn() {
}
#Override
public int hashCode() {
int hash = 0;
hash += (columnName != null ? columnName.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
if (!(object instanceof TableColumn)) {
return false;
}
TableColumn other = (TableColumn) object;
if ((this.columnName == null && other.columnName != null) || (this.columnName != null && !this.columnName.equals(other.columnName))) {
return false;
}
return true;
}
#Override
public String toString() {
return getColumnName();
}
}
Now we are ready to construct a list of POJO. Use the sample code below to construct get your result as List of POJOs.
public List<TableColumn> findTableColumns(String table) {
List<TableColumn> listTables = new ArrayList<>();
EntityManager em = emf.createEntityManager();
Query q = em.createNativeQuery(TABLE_COLUMNS, TableColumn.class).setParameter(1, table);
listTables = q.getResultList();
em.close();
return listTables;
}
Also, don't forget to add in your POJO class in persistence.xml! It can be easy to overlook if you are used to your IDE managing that file for you.
Had the same kind of problem where I wanted to return a List of POJOs, and really just POJOs (call it DTO if you want) and not #Entity annotated Objects.
class PojoExample {
String name;
#Enumerated(EnumType.STRING)
SomeEnum type;
public PojoExample(String name, SomeEnum type) {
this.name = name;
this.type = type;
}
}
With the following Query:
String query = "SELECT b.name, a.newtype as type FROM tablea a, tableb b where a.tableb_id = b_id";
Query query = getEntityManager().createNativeQuery(query, "PojoExample");
#SuppressWarnings("unchecked")
List<PojoExample> data = query.getResultList();
Creates the PojoExample from the database without the need for an Entity annotation on PojoExample. You can find the method call in the Oracle Docs here.
edit:
As it turns out you have to use #SqlResultSetMapping for this to work, otherwise your query.getResultList() returns a List of Object.
#SqlResultSetMapping(name = "PojoExample",
classes = #ConstructorResult(columns = {
#ColumnResult(name = "name", type = String.class),
#ColumnResult(name = "type", type = String.class)
},
targetClass = PojoExample.class)
)
Just put this anywhere under your #Entity annotation (so in this example either in tablea or tableb because PojoExample has no #Entity annotation)
I have the following mapping in my Play! app using JPA:
#Entity
public class Contact extends Model {
public String name;
#ManyToMany(mappedBy = "contacts", fetch = FetchType.EAGER)
public Set<Category> categories = new HashSet<Category>();
public void addCategory(Category c) {
this.categories.add(c);
if (!c.contacts.contains(this)) {
c.contacts.add(this);
}
}
#PreRemove
public void preRemove() {
for (Category c : this.categories) {
c.contacts.remove(this);
}
this.categories = null;
}
}
#Entity
public class Category extends Model {
public String name;
#ManyToMany
public Set<Contact> contacts = new HashSet<Contact>();
public void addContact(Contact c) {
this.contacts.add(c);
if (!c.categories.contains(this)) {
c.categories.add(this);
}
}
#PreRemove
protected void preRemove() {
for (Contact c : this.contacts) {
c.categories.remove(this);
}
this.contacts = null;
}
}
Deleting Category works fine, the relationship is updated correctly. If I delete a Contact however, I'm getting a constraint violation:
Caused by: org.h2.jdbc.JdbcBatchUpdateException: Referential integrity constraint violation: "FK34B085DF487AF903:
PUBLIC.CATEGORY_CONTACT FOREIGN KEY(CONTACTS_ID) REFERENCES PUBLIC.CONTACT(ID)"; SQL statement:
delete from Contact where id=? [23003-149]
How can I ensure that deleting a Contact will not delete the Category but will only remove the relationship?
EDIT: Duh! The issue was I also had a User object which had references to both Contact and Category. I missed clearing that relationship. The following is the change to preRemove() method in Contact class:
#PreRemove
public void preRemove() {
for (Category c : this.categories) {
c.contacts.remove(this);
}
this.user.contacts.remove(this);
for (Category c : this.user.categories) {
c.contacts.remove(this);
}
//It's important to save the user
this.user.save();
}
An other solution is to manually remove elements from the list and save it, before deleting the main entity :
while( !contact.categories.isEmpty() ) {
contact.categories.remove(0);
}
contact.save();
contact.delete();