JPA manyToMany bidirectional mapping tries to use an not exist table - jpa

Bidirectional ManyToMany mapping is using EMPLOYEE_PROJECT relation table instead of EMP_PROJ table described in mapping. EMPLOYEE_PROJECT does not exist on db. Eclipselink version is 2.7.3 and jpa version is 2.2
#Entity
public class Employee extends Base implements Serializable {
/** explicit set serialVersionUID */
private static final long serialVersionUID = 1L;
#Column(name = "FIRSTNAME")
private String firstname;
#ManyToMany
#JoinTable(name = "EMP_PROJ", joinColumns = #JoinColumn(name = "EMP_ID"), inverseJoinColumns = #JoinColumn(name = "PROJ_ID"))
private List<Project> projects;
public List<Project> getProjects() {
return projects;
}
public void setProjects(List<Project> projects) {
this.projects = projects;
Project Class
#Entity
public class Project extends Base implements Serializable {
/** explicit set serialVersionUID */
private static final long serialVersionUID = 1L;
#Column(name = "NAME")
private String name;
#ManyToMany(mappedBy="projects")
Set<Employee> employees = new HashSet<Employee>();
Problem is when query run
#Test
public void save_employee(){
EntityManager em = emf.createEntityManager();
Employee emp1 = em.find(Employee.class, new Integer(1));
Project p = new Project();
p.setName("Name1");
p.getEmployees().add(emp1);
p = em.merge(p);
assertNotNull(p);
Employee emp2 = em.find(Employee.class, new Integer(1));
assertEquals(1, emp2.getProjects().size());
em.close();
}
Following exception:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.3.v20180807-4be1041): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.h2.jdbc.JdbcSQLException: Table "EMPLOYEE_PROJECT" not found; SQL statement:
SELECT t1.ID, t1.DESCRIPTION, t1.NAME, t1.VERSION FROM EMPLOYEE_PROJECT t0, PROJECT t1 WHERE ((t0.Employee_ID = ?) AND (t1.ID = t0.projects_ID)) [42102-197]
Error Code: 42102
Base.java code is as following
#MappedSuperclass
public class Base {
protected int id;
protected int version;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Version
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
}

Related

CriteriaAPI + subquery creates wrong SQL (invalid identifier)

Not sure what I'm dong wrong so I'm guessing this is a bug. I'm trying to create a simple subquery but Eclipselink produces wrong SQL so the execution fails.
Error message
[EL Warning]: 2022-01-17 17:00:29.258--UnitOfWork(1407952056)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.9.v20200130-0143b822bc): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: ORA-00904: "T1"."ID"."T1"."ID": invalid identifier
Error Code: 904
Call: SELECT COUNT(t0.ID) FROM Order t0 WHERE t0.OUTPUT IN (SELECT t1.ID.t1.ID FROM Process t1 WHERE (t1.OWNER = ?))
bind => [0]
Query: ReportQuery(referenceClass=Order sql="SELECT COUNT(t0.ID) FROM Order t0 WHERE t0.OUTPUT IN (SELECT t1.ID.t1.ID FROM Process t1 WHERE (t1.OWNER = ?))")
Sample code
EntityManager em = ApplicationContextListener.createEntityManager();
try {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<Order> root = cq.from(Order.class);
cq.select(cb.count(root));
// Process subquery
Subquery<Long> sqProcess = cq.subquery(Long.class);
Root<Process> sqProcessRoot = sqProcess.from(Process.class);
Path<Long> processId = sqProcessRoot.get("id");
sqProcess.select(processId)
.where(cb.equal(sqProcessRoot.get("owner"), cb.parameter(String.class, "person")));
cq.where(cb.in(root.get("processOutput")).value(sqProcess));
TypedQuery<Long> tq = em.createQuery(cq);
int count = tq.setParameter("person", loggedInPerson).getSingleResult().intValue();
log.debug("SQL count string: {}", tq.unwrap(JpaQuery.class).getDatabaseQuery().getSQLString());
log.debug("Count = {}", count);
} finally {
em.close();
}
Order
#Entity
#Table(name = "Order")
public class Order implements Serializable {
private static final long serialVersionUID = 2804475880693788686L;
#Id
#SequenceGenerator(name = "ORDER_ID_GENERATOR", sequenceName = "ORDER_SEQ", allocationSize = 1, initialValue = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ORDER_ID_GENERATOR")
private long id;
// bi-directional many-to-one association to Process
#ManyToOne
#JoinColumn(name = "OUTPUT")
private Process processOutput;
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public Process getProcessOutput() {
return this.processOutput;
}
public void setProcessOutput(Process processOutput) {
this.processOutput = processOutput;
}
}
Process
#Entity
#Table(name = "Process")
public class Process implements Serializable {
private static final long serialVersionUID = -2021620806203228247L;
#Id
#SequenceGenerator(name = "PROCESS_ID_GENERATOR", sequenceName = "PROCESS_SEQ", allocationSize = 1, initialValue = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PROCESS_ID_GENERATOR")
#Expose
private long id;
#ManyToOne
#JoinColumn(name = "OWNER")
private Person owner;
#XmlTransient
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public Person getOwner() {
return owner;
}
public void setOwner(Person owner) {
this.owner = owner;
}
}

Project data from different tables to a model

I defined my model classes like below.
#Entity
#Table(name = "my_employee")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
#OneToMany(cascade = CascadeType.ALL)
#JoinTable(name = "emp_address_mapping", joinColumns = #JoinColumn(name = "emp_id"), inverseJoinColumns = #JoinColumn(name = "address_id"))
private List<Address> addresses = new ArrayList<Address>();
.......
.......
}
#Entity
#Table(name = "my_address")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String country;
.....
.....
}
public class EmployeeDetails {
private int empId;
private String name;
private String country;
......
......
}
How can I write a query using #Query annotation to populate all the EmployeeDetails.
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
#Query("SELECT new com.sample.app.model.EmployeeDetails......")
List<EmployeeDetails> getEmployeeDetails();
}
Create the constructor in EmployeeDetails
public EmployeeDetails(int id,String name,String country){
this.id=id;
this.name=name;
this.country=country;
}
Try this query
To get all employee details:
SELECT new com.sample.app.model.EmployeeDetails(e.id,e.name,a.country) from Employee e,Address a

Jpa Auditing dont save data in table auditing

I have to implementes Auditing in my aplication.. i inserting this data correctly
but i want to save all atributter from my Entity ,
Exemple, name, epigrafe, .. and olthers.
I implemented the mothod but dosent work, just dont save the atributte..
lets see..
#Entity
#EntityListeners(AuditingEntityListener.class)
#Table(name = "logradouros_historico", schema = "aud")
public class LogradourosHistorico {
#Id
#GeneratedValue
private Long id;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "id_logradouro")
private Logradouros logradouro;
#CreatedBy
private String modificadoPor;
#CreatedDate
#Temporal(TemporalType.TIMESTAMP)
private Date modifiedDate = new Date();
#Enumerated(EnumType.STRING)
private Acoes acao;
#Column(name = "nome")
private String nome; //nome do logradouro
public LogradourosHistorico() {
super();
}
public LogradourosHistorico(Logradouros logradouro, String modificadoPor,
Acoes acao) {
super();
this.logradouro = logradouro;
this.modificadoPor = modificadoPor;
this.acao = acao;
}
//getters and setters
my class entityListner
public class LogradourosEntityListener {
#PostPersist
public void prePersist(Logradouros target) {
perform(target, Acoes.INSERTED);
}
#PreUpdate
public void preUpdate(Logradouros target) {
perform(target, Acoes.UPDATED);
}
#PreRemove
public void preRemove(Logradouros target) {
perform(target, Acoes.DELETED);
}
#Transactional()
private void perform(Logradouros target, Acoes acao) {
target.getNome();
EntityManager entityManager = BeanUtil.getBean(EntityManager.class);
entityManager.persist(new LogradourosHistorico(target, acao));
}
}
my class Logradouros
#Entity
#EntityListeners(LogradourosEntityListener.class)
#Table(name = "logradouros", schema = "glb", uniqueConstraints= #UniqueConstraint(columnNames={"id_entidade", "idLogradouro"}))
public class Logradouros extends Auditable<String> implements Serializable {
private static final long serialVersionUID = 3703309412387185484L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int idLogradouro;
#Column(name = "cep_geral")
private String cepGeral;
#Column(name = "epigrafe")
private String epigrafe;
#NotNull
#Column(name = "nome")
private String nome;
#Column(name = "nome_exibicao")
private String nomeExibicao;
#JoinColumn(name = "id_entidade")
#ManyToOne(/*cascade = CascadeType.ALL*/)
private Entidades entidade;
#NotNull
#JoinColumn(name = "id_municipio")
#ManyToOne(/*cascade = CascadeType.ALL*/)
private Municipios municipio;
// gettrs and settrs
so what i did wrong because i cant get the nome of entity Logradouros

Spring Data JPA Specification Manyto One relationship

I have two entities in Spring Data JPA:
User--->* TaxPayment
The goal is to get the all the taxpayments related to user_id:
User.java
public class User extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
..........
}
TaxPayment.jva
public class TaxPayment implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Column(name = "payment_date", nullable = false)
private LocalDate paymentDate;
#NotNull
#Column(name = "amount", precision=10, scale=2, nullable = false)
private BigDecimal amount;
#Column(name = "reference")
private String reference;
#ManyToOne
private User user;
public Long getId() {
return id;
}..
}
I dont wan't to have oneTOMany Annotation from User.java and the column mapped in the Taxpayment as user_id.
Specification class as follows:
final class TaxPaymentSpecification {
private TaxPaymentSpecification(){
}
static Specification<TaxPayment> hasUser(Long userId){
return new Specification<TaxPayment>() {
#Override
public Predicate toPredicate(Root<TaxPayment> arg0, CriteriaQuery<?> arg1,
CriteriaBuilder arg2) {
// TODO Auto-generated method stub
Root<TaxPayment> root = arg0;
Subquery<Long> subqry = arg1.subquery(Long.class);
Root<User> user = subqry.from(User.class);
final Join<User,TaxPayment> taxpays = root.join("user");
subqry.select(taxpays.<Long> get("user_id"));
subqry.where(arg2.equal(user.<Long> get("id"),userId));
return arg2.in(arg0.get("user_id")).value(subqry);
}
};
}
}
Is specification is correct or wrong as per my goal to get all the TaxPayment related to user_id?
There is no need to use subquery if you already know the userId, which will be the value of user_id in TaxPayment table:
#Override
public Predicate toPredicate(Root<TaxPayment> arg0, CriteriaQuery<?> arg1,
CriteriaBuilder arg2) {
return arg2.equal(arg0.get("user_id"), userId);
}

Error on em.getTransaction().commit(); using the JPA #Embeddable annotation

I have some problems with #Embeddable in JAVA JPA.
I have an entity class named "Author":
#Entity
#Table(name = "author")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Author.findAll", query = "SELECT a FROM Author a"),
...})
public class Author implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "aID")
private Integer aID;
#Column(name = "aName")
private String aName;
#Column(name = "aSurname")
private String aSurname;
#Column(name = "aPhone")
private Integer aPhone;
#Embedded
#AttributeOverrides({
#AttributeOverride(name="city",column=#Column(name="Address")),
#AttributeOverride(name="street",column=#Column(table="Address")),
#AttributeOverride(name="number",column=#Column(table="Address"))
}) private Address address;
// set and get methods.
}
Also I have an Embeddable class named "Address":
#Embeddable
#Table(name = "Address")
#XmlRootElement
public class Address implements Serializable
{
private static final long serialVersionUID=1L;
#Column(name="city")
private String city;
#Column(name="street")
private String street;
#Column(name="number")
private int number;
// get and set methods.
}
In my main class I want to insert this values to the database. (I use mySQL) But I am getting an error on this line: em.getTransaction.commit();
public class CreateAuthor extends javax.swing.JFrame {
private static final String PERSISTENCE_UNIT_NAME = "Project";
private static EntityManagerFactory emf;
public void CreateAuthor() {
initComponents();
}
private void ekleButtonActionPerformed(java.awt.event.ActionEvent evt) {
emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Author author = new Author();
author.setAID(3);
author.setAName("Sheldon");
author.setASurname("Smith");
author.setAPhone(768987);
Address adr = new Address();
adr.setCity("Paris");
adr.setStreet("cinar");
adr.setNumber(12);
author.setAddress(adr);
em.persist(author);
em.getTransaction().commit(); /// error occured
em.close();
}
}
On my database side, I have Author table (aID(pk),aName,aSurname,aPhone)
Address Table (city,street,number)
Do you have any idea why an error is occured?
The goal of Embeddable is to have fields of an object (Address) stored in the same table as the entity's table (Author -> author).
If you want to save them in another table, than Address should be an entity on its own, and there should be a OneToOne or ManyToOne association between Author and Address. The mapping, as is, don't make any sense.