ForeignCollection throws SQLException on iterating using streams - java

I have three entity classes: PlayerData, IpData, and TwinData.
Both TwinData and IpData refer to PlayerData with a foreign key.
Here is the code:
#DatabaseTable
public class PlayerData {
#DatabaseField(generatedId = true)
private int id;
#DatabaseField
private UUID uuid;
#ForeignCollectionField
private ForeignCollection<IpData> ips;
#ForeignCollectionField
private ForeignCollection<TwinData> twins;
// Getters and setters...
}
#DatabaseTable
public class IpData {
#DatabaseField(generatedId = true)
private int id;
#DatabaseField(foreign = true)
private PlayerData playerData;
#DatabaseField
private Date firstUsage;
#DatabaseField
private String address;
// Getters and setters...
}
#DatabaseTable
public class TwinData {
#DatabaseField(generatedId = true)
private int id;
#DatabaseField(foreign = true)
private PlayerData mainPlayer;
#DatabaseField
private boolean adminNoticed;
#DatabaseField
private UUID uuid;
// Getters and setters...
}
When I try to iterate over PlayerData.ips with streams, I get SQLException [SQLITE_ERROR] SQL error or missing database (no such column: playerData_id). Tables are auto-generated with TableUtils.createIfNotExists().
This is the code that throws that exception:
// playerData is retrieved from Dao<PlayerData, Integer>
playerData.getIps().stream().noneMatch(ip -> ip.getAddress().equals(playerIp))
I just don't really get why it attempts to select playerData_id column.
Should I manually create database tables for TwinData and IpData with playerData_id column? Haven't tried this yet, but I don't think it would help.

When I try to iterate over PlayerData.ips with streams, I get SQLException[SQLITE_ERROR] SQL error or missing database (no such column: playerData_id). Tables are auto-generated with TableUtils.createIfNotExists().
You will get that error if playerData_id is not a field in the table. I'm surprised that TableUtils.createIfNotExists() did not create a field playerData_id in the IpData table. I suspect that the tables existed already and you are not using ORMLite generated schema.
By default when ORMLite sees a foreign = true field, it will store the id of that type in the entity in question. See the foreign fields documentation. If your schema is defining the relationship between the entities differently, for example with another table to define the relationship, then you will need to setup that entity by yourself and query it using the DAO for that entity.
You maybe should look at the foreign object example for more information.
Hope this helps.

Related

How to do one to many relationships in JDBC?

I have class two classes
i want to perform one to many relationship
public class Teacher {
private int id;
private String name;
private List<Class> classes;
}
public class Class {
private int id;
private String className;
}
I need to retrieve data and print data from the database
Teacher Classes
Kumar A1,B3,B4
Deepa A1,A2,C1
Alex B2,D1,D2
I don't Know how to retrive one to many relationship data in JDBC
please suggest me what should i do?
I do know about 2 ways to do it with jdbc
You need to select all teachers first, then for each teacher select his classes.
select * from teacher
then map results to your teacher class then on java side make a for each loop and fetch class by teacher_id for each teacher
select * from class where teacher_id = :teacher_id
You can select all teachers and classes like that:
select * from teacher t
left join class c on c.teacher_id = t.teacher_id
but you will get duplicate data of teacher becouse in each row you will fetch data for teacher also and you will need to organize it on Java side.
So I've been working recently with Spring JDBC myself. This is something similar with what I've come up with by reading here and there. I really appreciate the simplicity of JDBC combined with the domain driven approach:
public class Teacher {
#Id private int id;
private String name;
#MappedCollection(idColumn = "teacher_id", keyColumn = "teacher_key")
private List<Class> classes;
//setters and getters
}
public class Class {
private int id;
private String className;
//setters and getters
}
Then you need to create the repository interface by extending CrudRepository from Spring JDBC, you don't need to create an extra repository to e.g. save Class data through Teacher :
interface TeacherRepository extends CrudRepository<Teacher, Integer> {}
The TeacherRepository will have the typical CRUD methods that allow you to read or write data from/to the database.
The sql code (this is postgres like, change to your specific dialect) would be something like this:
create table teachers(
id serial primary key,
name text
)
create table classes(
id serial primary key,
class_name text,
teacher_id int references teachers(id),
teacher_key int
)
Where the teacher_key column is used to return an ordered list of classes. If you don't care about the classes ordering you can just return a set instead of a list:
public class Teacher {
#Id private int id;
private String name;
#MappedCollection(idColumn = "teacher_id")
private Set<Class> classes;
//setters and getters
}
public class Class {
private int id;
private String className;
//setters and getters
}
the sql code:
create table teachers(
id serial primary key,
name text
)
create table classes(
id serial primary key,
class_name text,
teacher_id int references teachers(id)
)
Here are my sources:
https://www.youtube.com/watch?v=ccxBXDAPdmo
https://spring.io/blog/2018/09/24/spring-data-jdbc-references-and-aggregates
https://lumberjackdev.com/spring-data-jdbc
https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#jdbc.repositories

Eclipselink - OneToOne Mapping

I am currently developing a little Group Management System and using java 8 with eclipselink and SqlLite.
#Entity
#Table(name = "T_GROUP")
public class Group {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private List<Permission> permissions;
private boolean defaultGroup;
private String prefix;
private String suffix;
private int rank;
private boolean build;
#OneToOne
private Group inherit;
/**
* Instantiates a new Group.
*/
public Group() {
}
...Getters Setters
}
The Field inherit references to another group that has other permissions, but the current group inherits all permissions from the other group.
How do I work with the field inherit? It is the same Type.
The OneToOne relation gives me following error:
Internal Exception: java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (near "CONSTRAINT": syntax error)
Error Code: 0
Call: ALTER TABLE T_GROUP ADD CONSTRAINT FK_T_GROUP_INHERIT_ID FOREIGN KEY (INHERIT_ID) REFERENCES T_GROUP (ID)
If your question is how to map the self referencing relationship, you can simply use #OneToOne annotation. This is already answered here JPA: How to have one-to-many relation of the same Entity type

Auto populate data in a table having foreign key

I have three classes corresponding to three tables in mysql database. My classes are as follows.
#Entity
#Table(name="location")
public class Location {
private Integer locationId;
private Integer hospitalId;
private Integer regionId;
private String locationCode;
private String locationName;
private String locationType;
#Entity
#Table(name="hospital_region")
public class HospitalRegion {
private Integer regionId;
private Integer hospitalId;
private String regionCode;
private String regionName;
public enum Status{Active,Inactive}
private Status status;
#Entity
#JsonAutoDetect
#Table(name="hospital_information")
public class HospitalInformation{
private Integer hospitalId;
private String shortName;
private String name;
private Integer packageId;
private Date implementationDate;
private Date validFrom;
private Date validUpTo;
private Date lastUpload;
public enum SubscriptionType{Free,Complimentary,Paid}
private Integer totalUsers;
I am making a Web Services for a Hospital Application where one region could have multiple locations(one-to-many) and one hospital could be in multiple regions(one-to-many).
So what I want to do is make a web service that would insert the data into location table.The ideal workflow should be that I shall pass every field in Location class as a json object to insert a record into the Location table.
My Business Logic should first check for my regionId and hospitalId value passed in the json object . If the hospitalId which is passed corresponds to the value of regionId in region table, if both correspond, only then data should be saved.
So I need help about how to implement it as a Business Logic.Thanks in advance
You miss the JPA relationships concept.
Your attributes are not annotated in the 3 classes.
You need to read about:
#ManyToOne Relation
#OneToMany Relation
#OneToOne Relation
#ManyToMany Relation
See more:
JPA Foreign Key Annotation
JPA Relationships 1
JPA Relationships 2

Hibernate criteria on embedded id member member value

I would like to find an entity using a critera with restriction on the value of an attribute of a second entity wich is a member of the embedded id of my first entity.
First entity :
#Entity
public class Car {
#EmbeddedId
private Id id = new Id();
private String color;
#Embeddable
public static class Id implements Serializable {
private static final long serialVersionUID = -8141132005371636607L;
#ManyToOne
private Owner owner;
private String model;
// getters and setters...
// equals and hashcode methods
}
// getters and setters...
}
Second entity :
#Entity
public class Owner {
#Id
#GeneratedValue (strategy = GenerationType.AUTO)
private Long id;
private String firstname;
private String lastname;
#OneToMany (mappedBy = "id.owner")
private List<Car> cars;
// getters and setters...
}
In this example, I would like to obtain the car with the color 'black', model 'batmobile' and the owner's firstname 'Bruce' (oops... spoiler ;) )
I tried to do something like that but it won't work :
List<Car> cars = session.createCriteria(Car.class)
.add(Restrictions.eq("color", "black"))
.add(Restrictions.eq("id.model", "batmobile"))
.createAlias("id.owner", "o")
.add(Restrictions.eq("o.firstname", "Bruce"))
.list();
Result :
Hibernate: select this_.model as model1_0_0_, this_.owner_id as owner_id3_0_0_, this_.color as color2_0_0_ from Car this_ where this_.color=? and this_.model=? and o1_.firstname=?
ERROR: Unknown column 'o1_.firstname' in 'where clause'
What is the right way to obtain what I want ?
update
I tried in hql :
String hql = "FROM Car as car where car.color = :color and car.id.model = :model and car.id.owner.firstname = :firstname";
Query query = em.createQuery(hql);
query.setParameter("color", "black");
query.setParameter("model", "batmobile");
query.setParameter("firstname", "Bruce");
List<Car> cars = query.getResultList();
It works but is there a way to do this with criteria ?
You forgot to add the #Column annotation on top of the firstname and lastname fields (and the color field in Car). In hibernate if a field is not annotated, it doesn't recognize it as a database field. This page should give you a good idea about how to set up your model objects.
NOTE: You can have the column annotation over the getters and be fine, but you didn't show the getters. Either place is fine.
Look at what HQL is spitting back out, specifically the statement (formated for easier reading):
select
this_.model as model1_0_0_,
this_.owner_id as owner_id3_0_0_,
this_.color as color2_0_0_
from Car this_
where
this_.color=?
and this_.model=?
and o1_.firstname=?
It looks like hibernate is translating the field "id.owner" to "o" as your alias told it to to, but for some reason it's not writing down that "id.owner=o" as intended. You may want to do some research into why it may be doing that.
As per https://hibernate.atlassian.net/browse/HHH-4591 there is a workaround.
You have to copy the needed relation-property of the #EmbeddedId (owner in this case) to the main entity (Car in this case) with insertable = false, updatable = false as follows
#Entity
public class Car {
#EmbeddedId
private Id id = new Id();
private String color;
#ManyToOne
#JoinColumn(name = "column_name", insertable = false, updatable = false)
private Owner owner;
#Embeddable
public static class Id implements Serializable {
private static final long serialVersionUID = -8141132005371636607L;
#ManyToOne
private Owner owner;
private String model;
// getters and setters...
// equals and hashcode methods
}
// getters and setters...
}
Then just create directly the alias instead of using the composite id property
List<Car> cars = session.createCriteria(Car.class)
.add(Restrictions.eq("color", "black"))
.add(Restrictions.eq("id.model", "batmobile"))
.createAlias("owner", "o")
.add(Restrictions.eq("o.firstname", "Bruce"))
.list();

ORMlite + MySQL Foreign Key Binding

How do I create auto delete cascade using ORMLite? I am using ormlite-core and omlite-jdbc version 4.8. I tried
public class Account {
// for QueryBuilder to be able to find the fields
public static final String NAME_FIELD_NAME = "name";
public static final String PASSWORD_FIELD_NAME = "passwd";
#DatabaseField(generatedId = true)
private int id;
#DatabaseField(columnName = NAME_FIELD_NAME, canBeNull = false)
private String name;
#DatabaseField(columnName = PASSWORD_FIELD_NAME)
private String password;
}
and another class
#DatabaseTable(tableName = "orders")
public class Order {
public static final String ACCOUNT_ID_FIELD_NAME = "account_id";
#DatabaseField(generatedId = true)
private int id;
#DatabaseField(foreign = true, columnName = ACCOUNT_ID_FIELD_NAME,
canBeNull = false,index = true, foreignAutoRefresh = true,
columnDefinition = "integer references document(id) on delete cascade")
private Account account;
#DatabaseField
private int itemNumber;
#DatabaseField
private int quantity;
#DatabaseField
private float price;
}
But When I delete the parent key record, no exception is being thrown and also, if try to insert records in order table with foreign key values which are not defined in the Account table, no exception is being thrown and the records get created and inserted in database.
But When i delete the parent key record , no exception is being thrown and also , if try to insert records in order table with foreign key values which are not defined in the Account table, no exception is being thrown and the records get created and inserted in database .
Stupid answer but shouldn't the column definition be:
integer references account(id) on delete cascade
I assume that the Account table is named account and not document. Otherwise your SQL looks good.
I would take a look at the schema on the MySQL side to make sure that it matches what you are expecting. I'd also try some inserts from the MySQL command line to see if you can figure out what is going on outside of ORMLite.
Hope this helps.

Categories

Resources