In my Spring Boot database project, I wanted this 'id' field to be auto-generated, unique Primary Key, but it's not. When I check the H2 database GUI there the Primary Key is some obscure, hidden 3rd column, which doesn't even list when I query the table. I attached a screenshot of it.
Screenshot of H2 database GUI:
This is my #Entity class.
package com.schabby.springdb;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Entry implements Serializable {
#GeneratedValue(strategy=GenerationType.AUTO)
#Id
private Long id;
private String text;
public Entry() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
Try this:
#Entity
public class Entry implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String text;
public Entry() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
Here IDENTITY indicates that the persistence provider must assign primary keys for the entity using the database identity column.
You can refer below reference to know more about different GenerationType.
Reference: https://docs.oracle.com/javaee/5/api/javax/persistence/GenerationType.html
Related
I'm trying to build an application with Netbean. I use Eclipse IDE & JPA API. the Entities is like this:
NATS.java
#Entity
#Table(name = "NATS")
Public Class NATS implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer code;
private String nName;
#Column(name = "cap_id") // for foreign key purpose
private Integer capId;
#OneToOne(cascade=CascadeType.PERSIST)
#PrimaryKeyJoinColumn(name = "cap_id" )
private City capital;
public City getCapital(){
return this.capital;
}
public void setCapital (City newcapital){
this.capital = newcapital;
}
... some gets & sets methods
}
City.java
#Entity
public class City implements Serializable {
private static final long serialVersionUID = 1L;
private String cityName;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
private Integer cityId;
public String getCityName() {
return cityName;
}
public void setCityName(String newcityName) {
this.cityName = newcityName;
}
public City(String ctname) {
this.cityName = ctname;
}
public Integer getcityId() {
return cityId;
}
public void setcityId(Integer ctId) {
this.cityId = ctId;
}
}
When i want to add new pair of NATS & City, i use this :
somebean.java
#Stateless
public class somebean {
#PersistenceContext(unitName = "TestLocal")
private EntityManager em;
public NATs insertNewCC(String capitalname, String countryname){
City newcapital = new City(capitalname );
NATS newcountry = new NATS();
newcountry.setNationName(countryname);
newcountry.setCapital(newcapital);
em.persist(newcountry); // both objects persisted well, with "capId" still null
return newcountry;
}
public void updateCapitalId(Nations country){
country.setCapitalId(country.getCapital().getcityId());
em.merge(country);
}
}
Here is the service:
genericResource.java
#Path("generic")
public class GenericResource {
#Context
private UriInfo context;
#EJB
private somebean r;
#GET
#Path("/inscountry")
#Produces("application/json")
public List<NATS> insCountry( #QueryParam("countryname") String countryname, #QueryParam("capitalname") String capitalname){
NATS newcountry = r.insertNewCC(capitalname, countryname);
//r.updateCapitalId(newcountry); <-- i want to avoid using this line
List<NATS> result= r.getListNATS();
return result;
}
When i comment the line : r.updateCapitalId(newcountry);
i get a pair of country and capital city with a relation displayed correctly in JSON, but when the session closes. it losses the relation because the foreign key is not saved. the capId in NATs entity is null after persist completed. So i need 1 persist & 1 merge to complete this. is there a better solution beside using that line i commented?
Thank you.
Redesign your entity NATS like this :
package com;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name = "NATS")
public class NATS
implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer code;
private String name;
// for foreign key purpose
#OneToOne(cascade = CascadeType.PERSIST)
#JoinColumn(name = "cap_id")
private City capital;
public City getCapital()
{
return this.capital;
}
public void setCapital(City newcapital)
{
this.capital = newcapital;
}
public Integer getCode()
{
return this.code;
}
public void setCode(Integer code)
{
this.code = code;
}
public String getName()
{
return this.name;
}
public void setName(String name)
{
this.name = name;
}
}
and then code for execution will remain same :
City newcapital = new City(capitalname);
NATS newcountry = new NATS();
newcountry.setName(countryname);
newcountry.setCapital(newcapital);
this.entityManager.persist(newcountry);
First of all, try to use indents and a formatter because your code is a mess. Second you want to save two entities (NATS and Country) so you must to uncomment the line where you update the city or persist one by one. If you are starting a new application I recommend you to use Spring boot and it's SpringRepository Interface to make those kind of things easier and clear.
I have 2 different tables: subjects and questions and I need to make SQL JOIN on these 2 tables. Table subjects has its attributes: name and shortcut. Table questions has its attributes: question_number, text, subject - in fact, subject from table questions is a shortcut of a subject.
I tried something like this, what I saw in one stackoverflow topic:
Query q = em.createNativeQuery("SELECT q.question_number, q.text, s.name, s.shortcut FROM "
+ "( questions q INNER JOIN subjects s ON q.subject=s.shortcut );", QuestionSubject.class);
QuestionSubject.class is an #Entity class and has attributes of both questions table and subjects table. After calling this method I saw that a new table with a name QUESTIONSUBJECT was created in my database and that is what I do not want to be done.
Can anyone help me with other solution?
P.S.: I am doing this in order to use the ouput as a response on HTTP request so I need to gather those two into one. I need to return either a List or JSON string.
EDIT: Using MySQL database.
questions table Entity class:
package model;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#Table(name = "questions")
#XmlRootElement
public class Question implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Basic(optional = false)
#Column(name = "question_number")
private Integer questionNumber;
#Column(name = "text")
private String text;
#Column(name = "subject")
private String subject;
public Question() {
}
public Question(Integer questionNumber) {
this.questionNumber = questionNumber;
}
public Question( String text, String subject) {
this.text = text;
this.subject = subject;
}
public Question(Integer questionNumber, String text, String subject) {
this.questionNumber = questionNumber;
this.text = text;
this.subject = subject;
}
public Integer getQuestionNumber() {
return questionNumber;
}
public void setQuestionNumber(Integer questionNumber) {
this.questionNumber = questionNumber;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
#Override
public int hashCode() {
int hash = 0;
hash += (questionNumber != null ? questionNumber.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Question)) {
return false;
}
Question other = (Question) object;
if ((this.questionNumber == null && other.questionNumber != null) || (this.questionNumber != null && !this.questionNumber.equals(other.questionNumber))) {
return false;
}
return true;
}
#Override
public String toString() {
return "Rest.Questions[ questionNumber=" + questionNumber + " ]";
}
}
subjects table Entity class.
package model;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#Table(name = "subjects")
#XmlRootElement
public class Subject implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 5)
#Column(name = "shortcut")
private String shortcut;
#Basic(optional = false)
#NotNull
#Lob
#Size(min = 1, max = 65535)
#Column(name = "name")
private String name;
public Subject() {
}
public Subject(String shortcut) {
this.shortcut = shortcut;
}
public Subject(String shortcut, String name) {
this.shortcut = shortcut;
this.name = name;
}
public String getShortcut() {
return shortcut;
}
public void setShortcut(String shortcut) {
this.shortcut = shortcut;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public int hashCode() {
int hash = 0;
hash += (shortcut != null ? shortcut.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Subject)) {
return false;
}
Subject other = (Subject) object;
if ((this.shortcut == null && other.shortcut != null) || (this.shortcut != null && !this.shortcut.equals(other.shortcut))) {
return false;
}
return true;
}
#Override
public String toString() {
return "Rest.Subjects[ shortcut=" + shortcut + " ]";
}
}
QuestionSubject Entity class:
package model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class QuestionSubject implements Serializable
{
#Id
#Column(name = "question_number")
private Integer questionNumber;
#Column(name = "text")
private String text;
#Column(name = "shortcut")
private String shortcut;
#Column(name = "name")
private String name;
public Integer getQuestionNumber() {
return questionNumber;
}
public void setQuestionNumber(Integer questionNumber) {
this.questionNumber = questionNumber;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getShortcut() {
return shortcut;
}
public void setShortcut(String shortcut) {
this.shortcut = shortcut;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The table gets created because you define a class named QuestionSubject annotated as #Entity. Per default the table name is the class name.
You could override the name like you did in Subjects with #Table(name = "subjects")
Nearly the same would happen if you would define a #ManyToMany mapping on related fields between classes Question and Subject without defining QuestionSubject class at all.
I would recommend to take a look here to get more information:
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Mapping/Relationship_Mappings/Collection_Mappings/ManyToMany
Edit
If you need a manyToMany mapping you need this table. Otherwise you can only have an oneToMany resp. manyToOne relation (using foreign keys).
I have written a piece of code that fetches entities from google datastore by filtering the entity with the supplied parent key. When I run the code I am getting java.lang.IllegalArgumentException.
I know the problem is with the way I am creating the parent key, can you please guide me how to effectively create a parent key for this use case?
I am getting the below exception in Myservice.java line 8
Method threw 'java.lang.IllegalArgumentException' exception
- Class hierarchy for class java.lang.Class has no #Entity annotation
Appengine v1.9.36,
Objectify v5.1.7,
JDK v1.7
Below is a sample code
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
#Entity
#Cache
public class ParentEntity {
#Id
Long id;
String name;
String value;
public static Key<ParentEntity> getKey(Long id){
return Key.create(ParentEntity.class, id);
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Another entity class
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Parent;
#Entity
#Cache
public class ChildEntity {
#Id
Long id;
#Parent Key<ParentEntity> application;
String city;
public static Key<ChildEntity> getKey(Long id){
return Key.create(Key.create(ParentEntity.class), ChildEntity.class, id);
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Key<ParentEntity> getApplication() {
return application;
}
public void setApplication(Key<ParentEntity> application) {
this.application = application;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
ServiceLaver that uses Objectify to fetch entities
import java.util.List;
import com.googlecode.objectify.ObjectifyService;
public class MyService{
public List<ChildEntity> filterByID(Long id){
return ObjectifyService.ofy().load().type(ChildEntity.class)
.filterKey(ChildEntity.getKey(id)).first().now();
}
}
change Your ParentEntity's method :
public static Key<ParentEntity> getKey(Long id){
return Key.create(ParentEntity.class, id);
}
to:
public String getWebSafeKey(){
return Key.create(ParentEntity.class, id).getString();
}
Now when you insert a parent entity then in response it will give you websafe key of that parent entity. Use this websafe key whenever you wants to access this inserted parent entity.
After that change:
public List<ChildEntity> filterByID(Long id){
return ObjectifyService.ofy().load().type(ChildEntity.class)
.filterKey(ChildEntity.getKey(id)).first().now();
}
To:
public List<ChildEntity> filterByID(String parentWebSafeKey){
return ObjectifyService.ofy().load().type(ChildEntity.class)
.ancestor(Key.create(parentWebSafeKey)).first().now();
}
Don't forget to create relationship between ParentEntity and ChildEntity while creating child entity using:
child_entity.application = Ref.create(parent_entity_key);
Following class fail to load with the Hibernate
package com.project.alice.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonProperty;
#Table
#Entity
public class AnyInformation<T, K> {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#JsonProperty("id")
private long id;
#JsonProperty("parent")
#ManyToOne
private T parent;
#ManyToOne
#JsonProperty("parentType")
private K parentType;
#JsonProperty("informationType")
private String informationType;
#JsonProperty("information")
private String information;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public T getParent() {
return parent;
}
public void setParent(T parent) {
this.parent = parent;
}
public K getParentType() {
return parentType;
}
public void setParentType(K parentType) {
this.parentType = parentType;
}
public String getInformationType() {
return informationType;
}
public void setInformationType(String informationType) {
this.informationType = informationType;
}
public String getInformation() {
return information;
}
public void setInformation(String information) {
this.information = information;
}
}
org.hibernate.AnnotationException:
Property com.project.alice.entities.AnyInformation.parent
has an unbound type and no explicit target entity.
Resolve this Generic usage issue or set an explicit target attribute
(eg #OneToMany(target=) or use an explicit #Type
Please help me here.
You should try something like -
#ManyToOne(targetEntity=Sample.class)
#JoinColumn(name = "<ID>")
private P parent;
#OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST, targetEntity=Sample.class)
private List<C> children;
Where, P and C extends Sample Class.
I hope it helps.
Note : As per my knowledge It can't be generic as you are expecting. You can not provide any object as a parameter. But the object should be related to the entity you are defining like Parent or Child. That's how it works in Hibernate.
If I create a Customer and Controller, then associate my Controller with a customer it saves fine.
If I then remove my controller it doesn't remove the relationship between them.
This causes an EntityNotFoundException when I load the Customer.
javax.persistence.EntityNotFoundException: Unable to find Controller with id 22
I'd like to know how to map this so that when a Controller is deleted the relationship is also deleted.
Database Tables
customer
controller
customer_controllers - mapping table.
The Controller's id is not getting removed from the customer_controllers mapping table.
#Entity
public class Customer implements Serializable{
private Integer id;
private Set<Controller> controllers;
#Id
#GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToMany(cascade={CascadeType.ALL})
public Set<Controller> getControllers()
{
return controllers;
}
public void setControllers(Set<Controller> controllers)
{
this.controllers = controllers;
}
}
#Entity
public class Controller implements Serializable{
private Integer id;
private String name;
private String abbreviation;
#Id
#GeneratedValue
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAbbreviation()
{
return abbreviation;
}
public void setAbbreviation(String abbreviation)
{
this.abbreviation = abbreviation;
}
}
If you have a ManyToMany then you should map Controller to Customer with a
#ManyToMany(mappedBy="controllers")
or the other way around, depending on which side is the owning side.
As you have it now the relation is not fully defined and it will fail on events like "Cascade".
Have you checked the javadoc for #ManyToMany?
It includes the above example mappings.
you need to make the relationship bidirectional, so that the controller object is aware of its relationship to the customer. Yhis means that when the controller is deleted the record in the join table is also deleted.
This isn't the exact mapping but it gives you the idea.
#Entity
public class Controller implements Serializable{
private Integer id;
private String name;
private String abbreviation;
private Set<Customer> customers;
#Id
#GeneratedValue
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAbbreviation()
{
return abbreviation;
}
public void setAbbreviation(String abbreviation)
{
this.abbreviation = abbreviation;
}
#ManyToMany(cascade={CascadeType.ALL})
public Set<Customer> getCustomers()
{
return customers;
}
public void setCustomers(Set<Customers> customers)
{
this.customers= customers;
}
}