So i have 3 tables: tutorials, topics, and tutorial_topics (maps the many to many relation).
I have this query:
select
t.id,
t.created,
t.created_by,
t.last_modified,
t.last_modified_by,
t.version,
l.name,
l.description,
top
from
tutorials t
inner join
localized_tutorial l
inner join topics as top
where l.name like '%Fish Cooking%' and l.locale='pt';
Now first, it tells me that t.id does not exist (i assume because is a derived table doesnt recognize the t.id from parent query), if i remove t.id verifications, says that topics in the first select is an unknown column, and if i put the join instead of the select (like below) just says i cant return a column with multiple objects. Im trying to send this to a spring boot app that receives this data. Is there any way to fix it?
select
t.id,
t.created,
t.created_by,
t.last_modified,
t.last_modified_by,
t.version,
l.name,
l.description,
(select * from topics topic inner join topics_tutorials ttopic where topic.id = ttopic.topics_id and t.id = ttopic.tutorials_id)
from
tutorials t
inner join
localized_tutorial l
where l.name like '%Java%' and l.locale='pt';
This is my tutorial table:
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Table(name = SQL.TUTORIAL_TABLE)
#Entity(name = SQL.TUTORIAL_ENTITY)
#ToString(doNotUseGetters = true, callSuper = true)
#EqualsAndHashCode(doNotUseGetters = true, callSuper = true)
public class TutorialDAO implements Serializable {
#Id
#GeneratedValue(generator = "uuid2", strategy = GenerationType.AUTO)
#Column(columnDefinition = "BINARY(16)", unique = true)
#GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
#CreatedDate
private LocalDateTime created;
#CreatedBy
private String createdBy;
#LastModifiedDate
private LocalDateTime lastModified;
#LastModifiedBy
private String lastModifiedBy;
#Version
private int version;
private static final long serialVersionUID = -1697137782136090241L;
private boolean exclusive;
#ToString.Exclude
#EqualsAndHashCode.Exclude
#ManyToMany(mappedBy = "tutorials", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private Set<TopicDAO> topics = new HashSet<>();
#ToString.Exclude
#EqualsAndHashCode.Exclude
#ElementCollection(fetch = FetchType.EAGER)
private Set<SectionDAO> sections = new HashSet<>();
#ToString.Exclude
#EqualsAndHashCode.Exclude
#ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
#JoinTable(name = "tutorial_courses", joinColumns = #JoinColumn(name = "tutorial_id"), inverseJoinColumns = #JoinColumn(name = "course_id"))
private Set<CourseDAO> courses = new HashSet<>();
#ToString.Exclude
#EqualsAndHashCode.Exclude
#OneToMany(mappedBy = "tutorial", cascade = { CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH }, orphanRemoval = true, fetch = FetchType.LAZY)
#MapKey(name = "localizedId.locale")
private Map<String, LocalizableTutorial> localizations = new HashMap<>();
}
And this is my Projection class
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString(doNotUseGetters = true, callSuper = true)
#EqualsAndHashCode(doNotUseGetters = true, callSuper = true)
public class LocalizedTutorialDAO extends AbstractDAO {
private static final long serialVersionUID = -8671921365618993655L;
private String name, description;
#ToString.Exclude
#EqualsAndHashCode.Exclude
private Set<TopicDAO> topics = new HashSet<>();
#ToString.Exclude
#EqualsAndHashCode.Exclude
private Set<SectionDAO> sections = new HashSet<>();
}
The topic entity is just an id and a topic string. i made it an entity in order to avoid duplicates.
My question is: from a tutorialDAO object how can i get a LocalizedTutorialDAO? i already can retrieve name and description from its localizations with the query:
select new com.fullstack.daos.projections.LocalizedTutorialDAO(t.id, t.created, t.createdBy, t.lastModified, t.lastModifiedBy, t.version, (VALUE(l)).name, (VALUE(l)).description) from tutorial t join t.localizations l where (VALUE(l)).name like %:name% and (KEY(l)) = :lang
The thing is when i need topics, it just gives the problems i described. However a spring generated FindById return the whole tutorial with topics, if i try to replicate it tho, nothing happens
From your queries, I think you want to select all columns from table topics but able to do it. Below is the method you can use to fetch them -
select t.id,
t.created,
t.created_by,
t.last_modified,
t.last_modified_by,
t.version,
l.name,
l.description,
top.[1st_col_topics_table],
top.[2nd_col_topics_table],
top.[3rd_col_topics_table],
top.[4th_col_topics_table]
...
from tutorials t
inner join localized_tutorial l on <join condition>
inner join topics_tutorials ttopic on t.id = ttopic.tutorials_id
inner join topics top on top.id = ttopic.topics_id
where l.name like '%Fish Cooking%' and l.locale='pt';
You cannot just write the table alias to fetch all columns. You have to mention all the columns explicitly.
I've got this entity:
#Getter
#Setter
#NoArgsConstructor
#ToString
#Accessors(chain = true)
#Entity
#Table(name = "offer_categs")
public class OfferCateg {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#Nullable
private String image;
#ManyToOne
#JoinColumn(name = "parent_id")
private OfferCateg parent;
#OneToMany(mappedBy = "parent",
cascade = CascadeType.REMOVE,
fetch = FetchType.LAZY,
orphanRemoval = true)
private Set<OfferCateg> children;
}
I'm trying to just create categories and subcategories. My problem is that when using the below method, parent_id might be null in case of a root category. How can I make the query to allow for that? I can't use IS NULL. Should I make two queries and be careful of the calling parent_id value ?
#Query(value = "SELECT * FROM offer_categs oc WHERE oc.parent_id = ?1 AND oc.name = ?2", nativeQuery = true)
OfferCateg findByNameAndParent(#Nullable Long parentId, String name);
EDIT
I changed the query to this and it seems to be working
#Query(value = "SELECT * FROM offer_categs oc WHERE " +
"(oc.parent_id = ?1 AND oc.name = ?2) OR" +
"(oc.parent_id IS NULL AND ?1 IS NULL AND oc.name = ?2)",
nativeQuery = true)
OfferCateg findByNameAndParent(#Nullable Long parentId, String name);
BUT...isn't this overkill ?! I'm sure it can be done more easily.
I'm currently having this issue: I have 3 tables: users, roles and users_roles as in the picture below:
whenever I edit any of the record in users table, the record of that user in the users_roles table will be lost.
For example, I changed the username of the user which holds the userId = 2, then in the users_roles table, the row of userId = 2 will be lost.
Anybody has any ideas of this problem? I'm using Spring with Hibernate
*UPDATE
In my Role.java
#ManyToMany(fetch = FetchType.EAGER, mappedBy = "roles")
private List<User> users;
In my User.java
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "users_roles", joinColumns = #JoinColumn(name = "userId", nullable = false) , inverseJoinColumns = #JoinColumn(name = "roleId", nullable = false) )
private List<Role> roles;
And in my UsersRoles.java
#Id
#Column(name="userId")
private int userId;
#Id
#Column(name="roleId")
private int roleId;
This is the DAO implementation method I used for Edit
#Override
public void edit(User user) {
session.getCurrentSession().saveOrUpdate(user);
}
P/S: this not only happens when I edit with my web-app, but also happens when I edit directly in MySQL environment. I don't know...
I have two classes:
#Entity
public class Tick {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#ManyToOne(optional = false)
#JoinColumn(name = "elitesystem_id", referencedColumnName = "id")
private EliteSystem eliteSystem;
private Date createDate;
#ManyToOne(optional = true)
#JoinColumn(name = "commander_id", referencedColumnName = "id")
private Commander commander;
private String address;
and
#Entity
public class Note {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#ManyToOne(optional = true)
#JoinColumn(name = "tick_id", referencedColumnName = "id")
private Tick tick;
private String text;
private Date createDate;
I want to select all ticks and get notes if there are any:
Query query = session.createQuery("select t, n from Note n right join n.tick t where t.commander.name = '123'");
List<Object[]> list = query.list();
This returns only Tick objects. What is the correct approach to get the Note information as well in 1 single query?
I could put a reference to a Note into the Tick class, but this doesnt sound right, as there are only a few notes, so the column in the Tick table would mostly be empty.
Create a New class for example:
public class TickNote {
private Tick tick;
private Note note;
public TickNote(Tick tick,Note note){
this.tick=tick;
this.note=note;
Then your query is:
Query query = session.createQuery("select NEW TickNote(t, n) from Note n right join n.tick t where t.commander.name = '123'");
List<TickNote> list = query.list();
I'm trying to implement a Keyword search functionality that returns a List of Keyword entities based on a field text match.
Right now, the query
select * from photo_keywords pk
inner join keywords k on pk.photo_id = k.keyword_id
inner join photos p on pk.keyword_id = p.photo_id
where k.keyword LIKE "%$SOME_SEARCH_VALUE%";
returns all matching photos for a given keyword search. I'd like to have this adapted to a #NamedQuery with the following Entity objects:
#Entity
#Table(name = "keywords")
public class Keyword implements Serializable{
#Id
#Column(name = "keyword_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column
private String keyword;
#ManyToMany(mappedBy = "keywords")
private List<Photo> photos;
//getters and setters
}
and
#Entity
#Table(name = "photos")
public class Photo implements Serializable{
#Id
#Column(name = "photo_id", nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "photo_name", nullable = false)
private String photoName;
#Column(name = "photo_path", nullable = false)
private String photoPath;
#Column(name = "upload_date", nullable = false)
private Date uploadDate;
#Column(name = "view_count", nullable = false)
private int viewCount;
#Column(name = "capture_date", nullable = false)
private Date captureDate;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "photo_metadata")
#MapKeyColumn(name = "metadata_name")
#Column(name = "metadata_value")
private Map<String, String> photoMetadata;
#ManyToMany
#JoinTable(name = "photo_keywords",
joinColumns = #JoinColumn(name = "keyword_id"),
inverseJoinColumns = #JoinColumn(name = "photo_id"))
public List<Keyword> keywords;
//getters and setters
}
This creates a join table photo_keywords, rather than a JoinColumn.
What I've tried so far with the Keyword entity:
#NamedQueries({
#NamedQuery(
name = "findKeywordByName",
query = "SELECT keyword from Keyword k WHERE k.keyword = :keyword"
)
})
which is executed via
public Keyword findKeywordByString(String keyword){
Keyword thisKeyword;
Query queryKeywordExistsByName = getEntityManager().createNamedQuery("findKeywordByName");
queryKeywordExistsByName.setParameter("keyword", keyword);
try {
thisKeyword = new Keyword((String) queryKeywordExistsByName.getSingleResult());
} catch (NoResultException e){
thisKeyword = null;
}
return thisKeyword;
}
This returns the Keyword, but with the photos property being null. This is to be expected, since I'm only selecting the keyword property. How can I adapt the SQL query above to a #NamedQuery?