Andorid room two primaryKeys , one autoGenerate - android-room

I want to have two primary keys, one should be autogenerated, I try do this:
#Entity(tableName = "object_to_group", primaryKeys = {"id" , "object_id"},)
public class ObjectsToGroup {
#ColumnInfo(name = "id",autoGenerate = true)
public long id;
but compilators show me error
when I do this:
#PrimaryKey(autoGenerate = true)
#ColumnInfo(name = "id")
public long id;
a compilator show me error, what I should to do?

It is not possible with a composite primary key to add auto-increment. As an alternative, you can use unique indices. for example
#Entity(tableName = "object_to_group", indices = {#Index(value =
{"object_id"}, unique = true)})
public class ObjectsToGroup {
#PrimaryKey(autoGenerate = true)
private int id;
#ColumnInfo(name = "object_id")
private int object_id;
}

Related

How do I add foreign keys into a new table in SpringBoot

I want to add the primary key from 2 tables (project and book mark) into a new table called ProjectBookmark which contains the primary key from my other two tables as foreign keys with the relationships shown below in springbok.
ERD Diagram
Below are my tables for Project and bookmark
Table 1
#Entity
public class Project {
#Id
#GeneratedValue
private long id;
#Column(name = "Project_Name", unique = true)
private String name;
#Column(name = "Description", unique = true)
private String description;
public Project(String name, String description) {
super();
this.name = name;
this.description = description;
}
Table 2
#Entity
public class Bookmark {
#Id
#GeneratedValue
private long id;
#Column(name = "Name", unique = true)
private String name;
#Column(name = "Type_of_resource", unique = true)
private String type;
#Column(name = "Description", unique = true)
private String description;
#Column(name = "URL", unique = true)
private String url;
public Bookmark(String name, String type, String description, String url) {
super();
this.name = name;
this.type = type;
this.description = description;
this.url = url;
}
Im not sure how to do the relationships and import in the primary keys as foreign keys to my table 3.
#Entity
public class ProjectBookmark {
}
If I understand your question correctly you need a ManyToMany relationship between Project and Bookmark.
You'll need to add the following code to your Project entity class.
#ManyToMany(fetch=FetchType.LAZY)
#JoinTable(name="project_bookmark",
joinColumns = {#JoinColumn(name="project_id", referencedColumnName="id")},
inverseJoinColumns = {#JoinColumn(name="bookmark_id", referencedColumnName="id")}
)
private Set<Bookmark> bookmarks = new HashSet<>();
You don't need an additional id column in your ProjectBookmark table.

How can I save ordered collection in JPA/Hibernate?

I have an main entity:
#Data
#Entity
#Table(name = "MAINS")
public class Main {
...
#OneToMany(mappedBy = "main", cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = LAZY)
private List<Chield> children;
And I have a child entity:
#Data
#Entity
#Table(name = "CHILDS")
public class Child {
#Id
#Column(name = "GUID")
private String guid;
#Column(name = "NAME")
private String name;
#Column(name = "Age")
private Integer age;
And I try to save one Main with many Child:
List<Child> children = new ArrayList<>();
for (int i = 0, i< 10; i++) {
Child child = new Child();
child.setId(i);
child.setName("Name"+i);
child.setAge(10+i);
children.add(child);
}
main.setChildren(children);
MainRepository.save(main);
But I need to save these children ordered. I can add a new column to Child - order and set child.setOrder(order++); and when I select this list I can sort it by order field.
But can I do it differently? Without adding of the new column?
If I get your question correctly it could be helpful to check such options:
OrderColumn
#OrderColumn(name = "index_id")
private List<Child> changes = new ArrayList<>();
OR
#OrderBy("id")
private Set<Child>list = new LinkedHashSet<>();
OR
#SortNatural
private SortedSet<Child> children = new TreeSet<Child>();
DOCS: naturalSort
OR for custom comparator: #SortComparator(SortById.class)
DOCS: customSort
public class SortById implements Comparator<Child> {
Logger log = Logger.getLogger(SortById.class.getSimpleName());
#Override
public int compare(Child o1, Child o2) {
log.info("Child.compare");
return o1.getId().compareTo(o2.getId());
}
}

Mapping objects from Room Persistence

I have classes - Subject.java
#Entity(tableName = Constants.SUBJECT_ENTITY)
public class Subject {
#PrimaryKey
private int id;
#ColumnInfo(name = "name")
private String name;
...
}
Grade.java
#Entity(tableName = Constants.GRADE_ENTITY,
foreignKeys = #ForeignKey(
entity = Subject.class,
onDelete = CASCADE,
parentColumns = "id",
childColumns = "subjectId"))
public class Grade implements Serializable {
#PrimaryKey
private int id;
#ColumnInfo(name = "semester")
private int semester;
#ColumnInfo(name = "subjectId")
private int subjectId;
...
}
SubjectAndAllGrades.java
public class SubjectAndAllGrades {
public int id;
public String name;
#Relation(parentColumn = "id", entityColumn = "subjectId")
public List<Grade> oceny;
...
}
I have performed some query in my SubjectDAO
#Query("SELECT distinct s.id as id, s.name as name " +
"FROM subject s, grade g " +
"WHERE s.id = g.subjectId " +
"AND g.semester = :semester ")
Flowable<List<SubjectAndAllGrades>> getSubjectAndAllItsGradesForSemester(int semester);
In this query as you can probably guess Im trying to select all Subjects with its grades with specific semester. However results of this query return list of SubjectAndAllGrades objects connected by subjectId key, but with no respect to the condition
g.semester = :semester
How could I achive this query?

Unable to save data to composite Table Via Spring Data rest json post

I have 3 Tables in db
training
- training_id (pk)
user_profile
- profile_id (pk)
-training_profile (composite table)
- training_id
- profile_id
I have already record in user_profile table having profile_id=44 and want to create new record for training table ,and also to associate this new training with already existing user_profile record which has id 44,but after post data is saved to training table but it is not inserted into lookup table user_training.
My Object Classes Are
- Training Class
#Entity
#Table(name = "training", schema = "public")
public class Training implements java.io.Serializable {
#Id #GeneratedValue
#Column(name = "training_id", unique = true, nullable = false)
private Long trainingId;
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "trainings")
private Set<UserProfile> userProfiles = new HashSet<UserProfile>(0);
#Column(name = "training_subject", length = 200)
private String trainingSubject;
public Training() {
}
public Long getTrainingId() {
return this.trainingId;
}
public void setTrainingId(Long trainingId) {
this.trainingId = trainingId;
}
public String getTrainingSubject() {
return this.trainingSubject;
}
public void setTrainingSubject(String trainingSubject) {
this.trainingSubject = trainingSubject;
}
public Set<UserProfile> getUserProfiles() {
return this.userProfiles;
}
public void setUserProfiles(Set<UserProfile> userProfiles) {
this.userProfiles = userProfiles;
}
}
UserProfile
#Entity
#Table(name = "user_profile", schema = "public")
public class UserProfile implements java.io.Serializable {
#Id #GeneratedValue
#Column(name = "profile_id", unique = true, nullable = false)
private Long profileId;
#Column(name = "profile_description")
private String profileDescription;
#ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.ALL })
#JoinTable(name = "user_training", schema = "public", joinColumns = {
#JoinColumn(name = "profile_id", nullable = false, updatable = false) }, inverseJoinColumns = {
#JoinColumn(name = "training_id", nullable = false, updatable = false) })
private Set<Training> trainings = new HashSet<Training>(0);
public UserProfile() {
}
public String getProfileDescription() {
return this.profileDescription;
}
public void setProfileDescription(String profileDescription) {
this.profileDescription = profileDescription;
}
public Set<Training> getTrainings() {
return this.trainings;
}
public void setTrainings(Set<Training> trainings) {
this.trainings = trainings;
}
}
My json post via postman
And Response I get
Response show that new training record inserted in table having training_id as 67
No association found for this new saved training
again it created new record for training and does not associate with existing user profile , I post curl -i -X POST -H "Content-Type:application/json" -d "{ \"trainingSubject\" : \"Oracle\", \"userProfiles\":[\"/userProfiles/44\"] }" http://localhost:8080/api/trainings
You could use the relative url assignment:
{
"trainingSubject": "oracle",
"userProfiles":["/userProfiles/44"]
}
Maybe also try with the full url: http://localhost:8080/api/userProfiles/44
EDITED
If you move the owning site of the ManyToMany relation to Training it will work with the above JSON. So currently the owner is allowed to set the realtions. If you do it like that:
#ManyToMany
#JoinTable(name = "user_training"
, joinColumns = {#JoinColumn(name = "profile_id") }
, inverseJoinColumns = {#JoinColumn(name = "training_id") })
private List<UserProfile> userProfiles = new ArrayList<>();
plus
#ManyToMany(mappedBy = "userProfiles")
private List<Training> trainings = new ArrayList<>();
Training owns the relation within userProfiles.
I think in your case it's the best option for now. Another option would be, when keeping the owner site at UserProfile on transactions, to update the relation there like:
PATCH http://localhost:8080/api/userProfiles/44
{
"trainings": ["trainings/66", "trainings/67"]
}
But with this you would need multible rest calls (1. POST new training and get the new Id 2. GET current training list 3. PATCH trainings list with newly added training)
Last option would be to add the REST-controller on your own.
Complete files for the first approach:
#Entity
#Table
public class Training implements Serializable {
#Id
#GeneratedValue
private Long trainingId;
#ManyToMany
#JoinTable(name = "user_training"
, joinColumns = {#JoinColumn(name = "profile_id") }
, inverseJoinColumns = {#JoinColumn(name = "training_id") })
private List<UserProfile> userProfiles = new ArrayList<>();
#Column(name = "training_subject", length = 200)
private String trainingSubject;
#Entity
#Table
public class UserProfile implements Serializable {
#Id
#GeneratedValue
private Long profileId;
#Column(name = "profile_description")
private String profileDescription;
#ManyToMany(mappedBy = "userProfiles")
private List<Training> trainings = new ArrayList<>();
public interface TrainingRepository extends JpaRepository<Training, Long> {
}
public interface UserProfileRepository extends JpaRepository<UserProfile, Long> {
}
With the upper JSON this will work, I tested it. You will not see the correct result directly in the response of curl-POST. To see the added relation you must follow the userProfiles-link like GET http://localhost:8080/transactions/<newId>/userProfiles

Hibernate saves child entity with null parent id

Hibernate doesn't want to save IDs for child entities. I have the following tables:
#Entity
#Table(name = "ct_orders")
data class Order(
#Id
#Column(name = "id")
#GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY)
val id: Int = 0,
#OneToMany(fetch = FetchType.LAZY, cascade = arrayOf(CascadeType.ALL), mappedBy = "order")
val route: List<Route>? = null,
...
)
#Entity
#Table(name = "ct_routes")
#JsonIgnoreProperties("id", "order")
data class Route(
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Int = 0,
#Column
val location: Point = GeoHelpers.point(),
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "order_id")
val order: Order? = null,
#Column
val title: String = ""
)
ct_routes saving with null in order_id. Is there some problem with relationships? Or, may be there is something wrong in my code?
Here is the part of code, which saves an Order entity:
val order = orderRepository.save(Order(
...
route = GeoHelpers.placesListToEntities(data.places),
...
))
fun placesListToEntities(points: List<PlaceDto>) = points.map {
Route(
location = Helpers.geometry(it.location.latitude, it.location.longitude),
title = it.title
)
}
You're modeling bidirectional #OneToMany and as shown in the example in the documentation you're responsible for setting the parent value on the child entity:
val order = orderRepository.save(Order(...).apply{
...
route = GeoHelpers.placesListToEntities(this, data.places),
...
})
fun placesListToEntities(order:Order, points: List<PlaceDto>) = points.map {
Route(
order = order,
location = Helpers.geometry(it.location.latitude, it.location.longitude),
title = it.title
)
}
PS. Since Route is an entity you could change your model a bit to enforce the constraints on the langauge level i.e:
class Route internal constructor() {
lateinit var order: Order
constructor(order: Order) : this() {
this.order = order
}
}
See this question for more details.

Resources