Java hibernate : Access foregin key - java

Processor.java
#Entity
public class Processor {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
private boolean running;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "firmware_id", referencedColumnName = "id")
private Firmware firmware;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
...
public Firmware getFirmware() {
return firmware;
}
public void setFirmware(Firmware firmware) {
this.firmware = firmware;
}
}
Firmware.java
#Entity
public class Firmware {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String version;
private String filename;
//Getter & Settger
}
ProcessorRepository.java
public interface ProcessorRepository extends CrudRepository<Processor, Integer> {
}
ProcessorController.java
...
#PutMapping(path = "/") // Map ONLY POST Requests
public #ResponseBody
Map<String, Object> addProcessor(#RequestBody Processor p) {
System.out.println("Put: " + p.getId());
processorRepository.save(p);
// I want to access : p.firmware_id;
// ex) p.setFirmware_id(8)
// ex) int tmp = p.getFirmware_id();
return Collections.singletonMap("success", true);
}
...
Below code is possible in java/spring-boot/hibernate?
// ex) p.setFirmware_id(8)
// ex) int tmp = p.getFirmware_id();

You can try to correct your mapping in this way:
#Entity
public class Processor {
// ...
// #NotFound ( action = NotFoundAction.IGNORE )
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "firmware_id", referencedColumnName = "id", insertable = false, updatable = false)
private Firmware firmware;
#Column(name = "firmware_id")
private Integer firmwareId;
// ...
}
and then set firmware_id via firmwareId.
Probably for this case you should use also #NotFound annotation (see this section of the documentation)

p.getFirmware().getId() or p.getFirmware().setId(id) whatever works

Related

Hibernate many-to-one mapping set previous foreign keys as NULL

I am new in Hibernate association mapping. When I tried to implement a small mapping logic all the previous foreign key is automatically update to Null
File Employee.java
#Entity
public class Employee extends CommonFields implements Serializable {
private static final long serialVersionUID = -723583058586873479L;
#Id
#Column(name = "id", insertable = false, updatable = false)
#GeneratedValue
private Long id;
private String employeeName;
#OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
#JoinColumn(name = "emp_id", referencedColumnName = "id")
private List<Education> education;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public List<Education> getEducation() {
return education;
}
public void setEducation(List<Education> education) {
this.education = education;
}
}
File Education.java
#Entity
public class Education extends CommonFields implements Serializable {
public Education() {
}
private static final long serialVersionUID = -723583058586873479L;
#Id
#Column(name = "id", insertable = false, updatable = false)
#GeneratedValue
private Long id;
private String course;
#ManyToOne
#JoinColumn(name = "emp_id")
private Employee employee;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}
Please anyone suggest a solution. I really stuck on this part last two days.

Update Associated entity on updatign foreign key - Hibernate

I have a mysql table which maintains data of drivers and maintains the city of the driver by using the foreign key mapping.
public class Drivers {
private Integer currentCityId;
private Integer id;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "current_city_id")
public Integer getCurrentCityId() {
return currentCityId;
}
public void setCurrentCityId(Integer currentCityId) {
this.currentCityId = currentCityId;
}
#ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
#JoinColumn(name = "current_city_id", insertable = false, updatable = false, nullable = true, unique = false)
public Cities getCities() {
return cities;
}
public void setCities(Cities cities) {
this.cities = cities;
}
}
#Entity
#Table(name = "cities", catalog = "mytable_production", uniqueConstraints = #UniqueConstraint(columnNames = "name"))
public class Cities implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private String aliasName1;
private String aliasName2;
private int stateId;
}
Now, I am updating the city of the driver by updating the foreignKey value in the table using
#Transactional
public void updateCityBizLogic(int driverId,int newCityId) {
//Some biz logic
Drivers d = driversDao.updateCity(driverId,newCityId);
log.info("Updated driverCity to {}",d.getCities.getName());
}
public class DriversDao {
#Transactional
public Drivers updateCity(int DriverId, int newCityId) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Drivers.class);
criteria.add(Restrictions.eq("id", Integer.parseInt(id)));
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
Drivers d = criteria.list().get(0);
d.setCurrentCityId(newCityId);
session.update(d);
return d;
}
}
But in the log line, it is printing the old city name. I want the session to update the associated entities when I update any of the foreign key ( like update the joined cities object, when I update the cityId)
Can someone point out what I am missing here and achieve it?

Join table on case insensitive PK and FK with JPA

I have 2 tables I want to join on PK and FK in JPA, but the PK is upper case and the FK lower case.
How do I map case insensitive association between Person -> GroupAssociationEntity?
My current mapping is not working.
#Entity
public class Person {
#Id
#Column(name = "id", columnDefinition = "nvarchar")
private String id;
#OneToMany(mappedBy = "person")
private List<GroupAssociationEntity> groups;
}
#Entity
#IdClass(GroupAssociationKey.class)
public class GroupAssociationEntity {
#Id
private String id;
#Id
private String memberOf;
#ManyToOne
#JoinColumn(name = "id", updatable = false, insertable = false, referencedColumnName = "id")
private Group group;
#ManyToOne
#JoinColumn(name = "memberOf", updatable = false, insertable = false, referencedColumnName = "id")
private Person person;
....
}
#Entity
public class Group {
#Id
#Column(name = "id")
private String id;
#OneToMany(mappedBy = "group")
private List<GroupAssociationEntity> persons;
......
}
I switched your mapping to:
#Entity(name = "Person")
public static class Person {
#Id
#Column(name = "id")
private String id;
#OneToMany(mappedBy = "person")
private List<GroupAssociationEntity> groups;
}
#Entity(name = "GroupAssociationEntity")
public static class GroupAssociationEntity {
#EmbeddedId
private GroupAssociationKey id;
#ManyToOne
#MapsId("id")
private Group group;
#ManyToOne
#MapsId("memberOf")
private Person person;
}
#Embeddable
public static class GroupAssociationKey implements Serializable{
private String id;
private String memberOf;
public GroupAssociationKey() {
}
public GroupAssociationKey(String id, String memberOf) {
this.id = id;
this.memberOf = memberOf;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMemberOf() {
return memberOf;
}
public void setMemberOf(String memberOf) {
this.memberOf = memberOf;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof GroupAssociationKey)) return false;
GroupAssociationKey that = (GroupAssociationKey) o;
return Objects.equals(getId(), that.getId()) &&
Objects.equals(getMemberOf(), that.getMemberOf());
}
#Override
public int hashCode() {
return Objects.hash(getId(), getMemberOf());
}
}
#Entity(name = "Group")
#Table(name = "groups")
public static class Group {
#Id
#Column(name = "id")
private String id;
#OneToMany(mappedBy = "group")
private List<GroupAssociationEntity> persons;
}
And run this test on both SQL Server and MySQL:
doInJPA( entityManager -> {
Person person1 = new Person();
person1.id = "abc1";
entityManager.persist(person1);
Person person2 = new Person();
person2.id = "abc2";
entityManager.persist(person2);
Group group = new Group();
group.id = "g1";
entityManager.persist(group);
GroupAssociationEntity p1g1 = new GroupAssociationEntity();
p1g1.id = new GroupAssociationKey("G1", "ABC1");
p1g1.group = group;
p1g1.person = person1;
entityManager.persist(p1g1);
GroupAssociationEntity p2g1 = new GroupAssociationEntity();
p2g1.id = new GroupAssociationKey( "G1", "ABC2" );
p2g1.group = group;
p2g1.person = person2;
entityManager.persist(p2g1);
} );
doInJPA( entityManager -> {
Group group = entityManager.find(Group.class, "g1");
assertEquals(2, group.persons.size());
} );
doInJPA( entityManager -> {
Person person = entityManager.find(Person.class, "abc1");
assertEquals(1, person.groups.size());
} );
And it works just fine. Check it out on GitHub.
#Entity
public class Person {
#Id
#Column(name = "id", columnDefinition = "nvarchar")
private String id;
}
#Entity
#IdClass(GroupAssociationKey.class)
public class GroupAssociationEntity {
#Id
private String id;
#Id
private String memberOf;
#ManyToOne
#JoinColumn(name = "id", updatable = false, insertable = false, referencedColumnName = "id")
private Group group;
#ManyToOne
#JoinColumn(name = "id", updatable = false, insertable = false, referencedColumnName = "id")
private Person person;
....
}
#Entity
public class Group {
#Id
#Column(name = "id")
private String id;
}
try this.

Using JPA NamedQuery to obtain result list

I want to get a list of results using the query as below:
SELECT x FROM XTreinamentosOrc x WHERE x.codEduca NOT IN (SELECT DISTINCT y.codCurso y FROM XRlz y WHERE y.matricula = :matricula)
I have used it in its entity class, but then I've got the Exception:
Caused by: javax.el.PropertyNotFoundException: The class 'br.com.bb.upb.diage.atb_treinamentos.entities.XTreinamentosOrc' does not have the property 'matricula'.
The matricula field is obtained when the user successfully logs in the app.
It should be setted in the NamedQuery via CDI to query the database.
The matricula field is located in another table different from the one mapped here.
How can I set the injected sessionChave String in parameter matricula, which is of XRlzConsolidado class type?
The bean:
#Named(value = "ExtratoBean")
#RequestScoped
public class ExtratoBean implements Serializable {
#EJB
private XTreinamentosOrcFacade xt;
#Inject
#SessionChave
private String sessionChave;
private List<XTreinamentosOrc> xTreinamentosOrcList;
public List<XTreinamentosOrc> getxTreinamentosOrcList() {
return QueryExtratoTreinamentos();
}
private List QueryExtratoTreinamentos() {
List<XTreinamentosOrc> extratoTreinamentosOrcList = null;
XRlzConsolidado x = new XRlzConsolidado();
x.setMatricula(sessionChave);
extratoTreinamentosOrcList = xt.findAllTreinamentosByMatricula(x);
return extratoTreinamentosOrcList;
}
}
There are 3 entities: XRlz, XRlzConsolidado and XTreinamentosOrc.
The XRlz:
#Entity
#Table(name = "XRlz", catalog = "diage", schema = "atb")
#XmlRootElement
//named queries
public class XRlz implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "id")
private Integer id;
#Size(max = 100)
#Column(name = "nome")
private String nome;
#Column(name = "uorPos")
private Integer uorPos;
#Size(max = 100)
#Column(name = "nomeUorPos")
private String nomeUorPos;
#Column(name = "codCurso")
private Integer codCurso;
#Size(max = 100)
#Column(name = "nomeCurso")
private String nomeCurso;
#Column(name = "qtdCursos2015")
private Integer qtdCursos2015;
#Size(max = 10)
#Column(name = "dtConclusao")
private String dtConclusao;
#JoinColumn(name = "matricula", referencedColumnName = "matricula")
#ManyToOne
private XRlzConsolidado matricula;
#JoinColumn(name = "dtRef", referencedColumnName = "id")
#ManyToOne
private XDatas dtRef;
//GETTERS AND SETTERS
public XRlzConsolidado getMatricula() {
return matricula;
}
public void setMatricula(XRlzConsolidado matricula) {
this.matricula = matricula;
}
public XDatas getDtRef() {
return dtRef;
}
public void setDtRef(XDatas dtRef) {
this.dtRef = dtRef;
}
//equals/hashcode/toString
}
The XRlzConsolidado:
#Entity
#Table(name = "XRlzConsolidado", catalog = "diage", schema = "atb")
#XmlRootElement
// NamedQueries
public class XRlzConsolidado implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 8)
#Column(name = "matricula")
private String matricula;
#Size(max = 100)
#Column(name = "nome")
private String nome;
#Column(name = "uorPos")
private Integer uorPos;
#Size(max = 100)
#Column(name = "nomeuorPos")
private String nomeuorPos;
#Column(name = "capacitacaoGestores")
private Integer capacitacaoGestores;
#Column(name = "capacitacaoAssessores")
private Integer capacitacaoAssessores;
#Column(name = "horas")
private Integer horas;
#Column(name = "bemEstar")
private Integer bemEstar;
#Column(name = "inovEfic")
private Integer inovEfic;
#Column(name = "qtdCursos2015")
private Integer qtdCursos2015;
#OneToMany(mappedBy = "matricula")
private Collection<XRlz> xRlzCollection;
public XRlzConsolidado() {
}
public XRlzConsolidado(String matricula) {
this.matricula = matricula;
}
public String getMatricula() {
return matricula;
}
public void setMatricula(String matricula) {
this.matricula = matricula;
}
// getters and setters
#XmlTransient
public Collection<XRlz> getXRlzCollection() {
return xRlzCollection;
}
public void setXRlzCollection(Collection<XRlz> xRlzCollection) {
this.xRlzCollection = xRlzCollection;
}
// hashCode()
#Override
public boolean equals(Object object) {
if (!(object instanceof XRlzConsolidado)) {
return false;
}
XRlzConsolidado other = (XRlzConsolidado) object;
if ((this.matricula == null && other.matricula != null) || (this.matricula != null && !this.matricula.equals(other.matricula))) {
return false;
}
return true;
}
// toString
}
The XTreinamentosOrc:
#Entity
#Table(name = "XTreinamentosOrc", catalog = "diage", schema = "atb")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "XTreinamentosOrc.findAll", query = "SELECT x FROM XTreinamentosOrc x"),
#NamedQuery(name = "XTreinamentosOrc.findAllTreinamentosByMatricula", query = "SELECT x FROM XTreinamentosOrc x WHERE x.codEduca NOT IN (SELECT DISTINCT y.codCurso FROM XRlz y WHERE y.matricula = :matricula)")})
public class XTreinamentosOrc implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#NotNull
#Column(name = "codEduca")
private int codEduca;
#Size(max = 100)
#Column(name = "nomeCurso")
private String nomeCurso;
#Column(name = "cargaHoraria")
private Integer cargaHoraria;
#JoinColumn(name = "tipo", referencedColumnName = "id")
#ManyToOne(optional = false)
private XTipo tipo;
#JoinColumn(name = "segmento", referencedColumnName = "id")
#ManyToOne(optional = false)
private XSegmento segmento;
#JoinColumn(name = "modalidade", referencedColumnName = "id")
#ManyToOne
private XModalidade modalidade;
#JoinColumn(name = "dtRef", referencedColumnName = "id")
#ManyToOne
private XDatas dtRef;
public XTreinamentosOrc() {
}
public XTreinamentosOrc(Integer id) {
this.id = id;
}
public XTreinamentosOrc(Integer id, int codEduca) {
this.id = id;
this.codEduca = codEduca;
}
// hashCode() {
#Override
public boolean equals(Object object) {
if (!(object instanceof XTreinamentosOrc)) {
return false;
}
XTreinamentosOrc other = (XTreinamentosOrc) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
}
Thanks in advance.
I believe the problem lies in the name of your query. findAllTreinamentosByMatricula() is a Property Expression and can refer only to a direct property of the managed entity. findAllTreinamentosByMatricula will look in the XTreinamentosOrc class for the property called matricula. When that property is not found in XTreinamentosOrc you get the exception:
Caused by: javax.el.PropertyNotFoundException: The class 'br.com.bb.upb.diage.atb_treinamentos.entities.XTreinamentosOrc' does not have the property 'matricula'.
You need to change the name of your query to something like:
#NamedQuery(name = "XTreinamentosOrc.find", query = "SELECT x FROM XTreinamentosOrc x WHERE x.codEduca NOT IN (SELECT DISTINCT y.codCurso FROM XRlz y WHERE y.matricula = :matricula)")})
(I may be off with the method name 'find() so you may need to do some more research' for acceptable format)
check out this documentation:
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-property-expressions
Could you post code for XRlzConsolidado? It probably contains a string field you want to compare with sessionChave. You are comparing field XRlz.matricula with string value, but it is of type XRlzConsolidado

Hibernate mapping in Java: org.hibernate.MappingException: Repeated column in mapping for entity

I try to gather statistics of visitors for two services. It consists of daily visitors statistics and overall record. Each service can be accessed by different names. For example, user, admin, support etc. Each will have its own record as own statistics.
Here is my DB structure:
service_one: id, name
service_two: id, name
daily_stats: id, date, service_one_id, service_one_visitors,
service_two_id, service_two_visitors, overall_visitors
record_stats: id, service_one_id, service_one_record,
service_one_record_date, service_two_id, service_two_record,
service_two_record_date
Here are the relations between tables:
service_one --- (one to many) ---> daily_stats(service_one_id)
service_one --- (one to many) ---> record_stats(service_one_id)
service_two --- (one to many) ---> daily_stats(service_two_id)
service_two --- (one to many) ---> record_stats(service_two_id)
Mapping for service_one (the same is for service_two). Also setters were omitted in order to shorten the example:
#Entity
#Table(name = "service_one")
public class ServiceOne implements Serializable {
private int id;
private String name;
private Set<RecordStats> recordStats = new HashSet<RecordStats>(0);
private Set<DailyStats> dailyStats = new HashSet<DailyStats>(0);
public ServiceOne() {}
public ServiceOne(int id, String name) {
this.id = id;
this.name = name;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", nullable = false, unique = true)
public int getId() {
return id;
}
#Column(name = "name")
public String getName() {
return name;
}
#OneToMany(fetch = LAZY, mappedBy = "service_one_id")
public Set<RecordStats> getRecordStats() {
return recordStats;
}
#OneToMany(fetch = LAZY, mappedBy = "service_one_id")
public Set<DailyStats> getDailyStats() {
return dailyStats;
}
}
daily_stats mapping:
#Entity
#Table(name = "daily_stats", uniqueConstraints = {
#UniqueConstraint(columnNames = "date")
})
public class DailyStats implements Serializable{
private int id;
private Date date;
private ServiceOne service_one_id;
private int service_one_visitors;
private ServiceTwo service_two_id;
private int service_two_visitors;
private int overall_visitors;
public DailyStats() {}
public DailyStats(DailyStats rec) {
this.id = rec.getId();
//...
}
#Id
#GeneratedValue
#Column(name = "id", nullable = false)
public int getId() {
return id;
}
#Temporal(DATE)
#Column(name = "date")
public Date getDate() {
return date;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceOne getService_one_id() {
return service_one_id;
}
#Column(name = "service_one_visitors")
public int getService_one_visitors() {
return service_one_visitors;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceTwo getService_two_id() {
return service_two_id;
}
#Column(name = "service_two_visitors")
public int getService_two_visitors() {
return service_two_visitors;
}
#Column(name = "overall_visitors")
public int getOverall_visitors() {
return overall_visitors;
}
}
record_stats mapping:
#Entity
#Table(name = "record_stats", uniqueConstraints = {
#UniqueConstraint(columnNames = "service_one_record_date"),
#UniqueConstraint(columnNames = "service_two_record_date")
})
public class RecordStats implements Serializable {
private int id;
private ServiceOne service_one_id;
private int service_one_record;
private Date service_one_rec_date;
private ServiceTwo service_two_id;
private int service_two_record;
private Date service_two_rec_date;
public RecordStats() {}
public RecordStats(RecordStats rec) {
this.id = rec.getId();
//...
}
#Id
#GeneratedValue
#Column(name = "id", nullable = false)
public int getId() {
return id;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceOne getService_one_id() {
return service_one_id;
}
#Column(name = "service_one_record")
public int getService_one_record() {
return service_one_record;
}
#Column(name = "service_one_record_date")
#Temporal(DATE)
public Date getService_one_rec_date() {
return service_one_rec_date;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceTwo getService_two_id() {
return service_two_id;
}
#Column(name = "service_two_record")
public int getService_two_record() {
return service_two_record;
}
#Column(name = "service_two_record_date")
#Temporal(DATE)
public Date getService_two_rec_date() {
return service_two_rec_date;
}
}
Trying to create new entry throws exception:
public static void main(String[] args) {
ServiceOne serviceOne = new ServiceOne();
serviceOne.setName("test");
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(serviceOne);
session.getTransaction().commit();
//get records
session = sessionFactory.openSession();
session.beginTransaction();
List result = session.createQuery("from service_one").list();
for (ServiceOne o : (List<ServiceOne>)result) {
System.out.println(o.getName());
}
session.getTransaction().commit();
session.close();
}
org.hibernate.MappingException: Repeated column in mapping for entity:
VisitorsCounter.model.entity.DailyStats column: id (should be
mapped with insert="false" update="false")
What is wrong with my mapping?
It seems to me that
#JoinColumn(name = "id", nullable = false)
public ServiceOne getService_one_id() {
return service_one_id;
}
in DailyStats is wrong; you should have name = "service_one_id".
You have the same problem in getService_two_id() and in methods of same names in RecordStats.
May I also ask why don't you name the references in the classes fields serviceOne and serviceTwo instead of service_one_id and service_two_id.

Categories

Resources