One to one realationship with ormlite - ormlite

How to implement one to one table relationship in Ormlite? Let’s say I have entities Country and Capital.
#DatabaseTable(tableName = "countries")
public class Country {
#DatabaseField(generatedId = true)
int id;
#DatabaseField
String name;
public Country() {
}
}
#DatabaseTable(tableName = "capitals")
public class Capital {
#DatabaseField(generatedId = true)
int id;
#DatabaseField
String name;
public Capital() {
}
}
Is it true that I need to have this field in Country class?
#DatabaseField(foreign = true)
Capital capital;
...and this field in Capital class?
#DatabaseField
Country country;

You just need the #DatabaseField in the class which the table contains the foreign key.
If countries contains capital_id, then you should add
#DatabaseField(columnName = "capital_id", foreign = true)
private Capital capital;

Related

method in ArangoRepository extension class using COLLECT in query annotation to group by and count not working

I have a simple node like this below
#Document("users")
public class User {
#Id // db document field: _key
private String id;
#ArangoId // db document field: _id
private String arangoId;
private String firstName;
private String lastName;
private String country;
public User() {
super();
}
public User(String id) {
this.id = id;
}
public User(String id, String country) {
this.id = id;
this.country = country;
}
// getter & setter
#Override
public String toString() {
return "User [id=" + id + ", name=" + firstName + ", surname=" + lastName + "]";
}
public String getId() {
return id;
}
}
here is the repository class but the method getListOfCountryAndNumUsers returns null even though i have inserted users with different countries into the database.
public interface UserRepository extends ArangoRepository<User, String> {
#Query("FOR u IN users COLLECT country = u.country WITH COUNT INTO length RETURN
{\"country\" : country, \"count\" : length }")
Iterable<CountryAndNumUsers> getListOfCountryAndNumUsers();
}
I think the problem could be with the the syntax of my query in the query annotation. I didnt see any direct example of using collect operation in the spring data arango db part of arangodb documentation here but I saw the collect operation in the section "high level operations" of arangoDb documentation here
Please Help. Thanks. !
So I discovered my error. It was in a class I didn't add in the question. That is the class for the return object of the method getListOfCountryAndNumUsers()
i.e class CountryAndNumUsers.
public class CountryAndNumUsers {
private String country;
private Integer numberOfUsers;
public CountryAndNumUsers(String country, Integer numberOfUsers) {
this.country = country;
this.numberOfUsers = numberOfUsers;
}
public String getCountry() {
return country;
}
public Integer getNumberOfUsers() {
return numberOfUsers;
}
}
so there was a mapping mismatch since the query returns an object with different field names. I changed the query to this below so that it matches
#Query("FOR u IN users COLLECT country = u.country WITH COUNT INTO length RETURN {\"country\" : country, \"numberOfUsers\" : length }")

Storing enum in separate table

I have entity Student and it has field like enum City. I know how to store enums in jpa via #Enumerated annotation, but I want to store enum in separate table and have foreign key from Student to City. But I have no idea how to implement.
City
public enum City {
PAVLOGRAD("Pavlograd")
,DNEPR("Dnepr");
private String shortName;
City(String shortName) {
this.shortName = shortName;
}
public String getShortName() {
return shortName;
}
}
Student
public class Student implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Enumerated(EnumType.ORDINAL)
private City city;
}

Find an entity which use a class Id

To find an object from entity with primary key we use em.find(Person.class, <Id>).
I'm using JPA EclipseLink and I have a Person entity which has a composite primary key(#classId),
the Person entity:
#Entity
#IdClass(PersonId.class)
public class Person {
#Id
private int id;
#Id
private String name;
public String getName() {
return name;
}
// getters & setters
}
and the PersonID:
public class PersonId implements Serializable {
private static final long idVersionUID = 343L;
private int id;
private String name;
// must have a default construcot
public PersonId() {
}
public PersonId(int id, String name) {
this.id = id;
this.name = name;
}
//getters & setters
//hachCode & equals
}
How to use em.find to get a Person object?
I found the solution :
PersonId personeId = new PersonId(33, "Jhon");
Person persistedPerson = em.find(Person.class, personeId);
System.out.println(persistedPerson.getID() + " - " + persistedPerson.getName());

Ormlite - change name of foreign key column

Is it possible to specify the name of the foreign key in OrmLite?
I have two tables
public class Order extends BaseData
{
#DatabaseField(id = true)
private Long order_ID;
...
#ForeignCollectionField(eager = true, maxEagerForeignCollectionLevel = 2)
private ForeignCollection<Vehicle> vehicleList;
}
public class Vehicle extends BaseData
{
#DatabaseField(id = true)
private long vehicle_ID;
...
#DatabaseField(canBeNull = false, foreign = true)
private Order order;
}
What I'd really like to do is include in the definition of my Vehicle class an order_id and then specify that ormlite uses this order_id as the foreign key field.
I've tried the below:
public class Vehicle extends BaseData
{
#DatabaseField(id = true)
private long vehicle_ID;
#DatabaseField
private long order_ID;
#DatabaseField(canBeNull = false, foreign = true, columnName = "order_ID")
private Order order;
}
However this gives error messages regarding duplicate columns when creating the database.
This question looks like one of my old answer : In ormlite, How can I have a foriegn field and a field column?.
It give you error because you creating 2 tables with the same name.
You shouldn't store the id in the database and put a setter. If you store the id in the database you will have duplicate information in. Just do :
public class Vehicle extends BaseData
{
#DatabaseField(id = true)
private long vehicle_ID;
private long order_ID;
#DatabaseField(canBeNull = false, foreign = true, columnName = "order_ID")
private Order order;
public void setOrder(Order order){
this.order=order;
order_ID = order.getId();
}
}

Creating JPA entity with composite primary key with #Id from #MappedSuperclass

I have a class hierarchy for JPA entities with the base class being a MappedSuperclass which has one ID defined. I am trying to use a composite key in a subclass however that does not seem to work
My code looks like this
#MappedSuperclass
public class BaseEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
protected Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
#Entity
#EntityListeners(EntityBaseListener.class)
#Inheritance(strategy=InheritanceType.JOINED)
#Table(name = "catalog_entity")
public class BaseCatalogEntity extends BaseEntity {
#Column(name = "created_at", nullable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date createdAt;
#Column(name = "updated_at", nullable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date updatedAt;
public void setCreatedAt(Date date)
{
createdAt = date;
}
public void setUpdatedAt(Date date)
{
updatedAt = date;
}
public Date getCreatedAt() {
return createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
}
#Entity
#Table(schema = "student_catalog")
#IdClass(value = StudentCatalog.StudentCatalogPK.class)
public class StudentCatalog extends BaseCatalogEntity {
#Id
#Column(name = "name", nullable = false, length = 100)
private String name;
#Id
#Column(name = "version", nullable = false)
private Integer version;
#Column(name = "description" , length = 255)
private String description;
#Column(name = "vendor" , length = 50)
private String vendor;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getVendor() {
return vendor;
}
public void setVendor(String vendor) {
this.vendor = vendor;
}
public static class StudentCatalogPK implements Serializable {
private Long id;
private String name;
private Integer version;
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 Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
#Override
public boolean equals(Object obj) {
boolean result = false;
if(obj != null && (obj instanceof StudentCatalogPK)) {
StudentCatalogPK other = (StudentCatalogPK)obj;
result = (Objects.equals(this.id, other.id) && Objects.equals(this.name, other.name) &&
Objects.equals(this.version, other.version));
}
return result;
}
#Override
public int hashCode() {
return (27780 + (this.id != null ? this.id.hashCode() : 0) +
(this.version != null ? this.version.hashCode() : 0) +
(this.name != null ? this.name.hashCode() : 0));
}
}
}
I get the following exception:
Exception Description: Invalid composite primary key specification. The names of the primary key fields or properties in the primary key class [com.example.jpa.StudentCatalog$StudentCatalogPK] and those of the entity bean class [class com.example.jpa.StudentCatalog] must correspond and their types must be the same. Also, ensure that you have specified ID elements for the corresponding attributes in XML and/or an #Id on the corresponding fields or properties of the entity class.
I am using Eclipselink 2.5.1. Is there a way I can get this to work without changing the BaseEntity and BaseCatalogEntity classes?
It is not legal in JPA to redefine the id in subclasses. This would lead to ambiguities in the table mappings as well as in polymorphic queries.
The desire to extend the key defined in a superclass is a common issue when business keys are used for DB identity. I would advise to use only surrogate keys (like UUID) for DB identity and business keys for instance identity.
Under following conditions:
your base entity should use TABLE_PER_CLASS inheritance (and as I can see it is)
your base entity (composite key) key is of the same type as that one you want to have in your derived class (so there should be also composite key of String and Integer).
You can use #AttributeOverride annotation under class declaration, removing #Id fields from it:
#AttributeOverride(name = "id", column = #Column(name = "NAME"))
This - in result, can change column name in derived entity's table and that's the most you can acheive.
When using #MappedSuperClass, it would be advisable to make the BaseEntity Class as abstract and then extending the Base class from other Entity classes.
Cleaner approach keeping inheritance in mind and designing your application.