I want to understand how to work with related entities in Hibernate.
There are two related entities:
#Entity
#Table(name = "usr")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false)
private String username;
#Column(nullable = false)
private String password;
#Column(nullable = false)
private String email;
private boolean active;
#Enumerated(EnumType.STRING)
private Role role;
#OneToMany(fetch = FetchType.LAZY,
mappedBy = "responsibleUser", cascade = CascadeType.ALL)
private List<GrowBox> growBoxes;
//def-constructor , getters, setters
}
and
#Entity
#Table(name = "growBoxes")
public class GrowBox {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
#Column(nullable = false)
private Integer length;
#Column(nullable = false)
private Integer width;
#Column(nullable = false)
private Integer height;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "responsibleGrowBox", cascade = CascadeType.ALL)
private List<Plant> plants;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "activeGrowBox", cascade = CascadeType.ALL)
private List<Sensor> sensors;
#ManyToOne
#JoinColumn(name = "user_id")
private User responsibleUser;
//def-constructor , getters, setters
}
I have registered mapping using annotations. Hope it is correct. And I want to find box by user Id, but don't know how HQL query should be written. 'Cause there is no "user_id" field in my Box Class. Instead there is "User responsibleUser" field. And smth like this won't work(should not)
#Autowired
SessionFactory sessionFactory;
#Override
public List<GrowBox> findByUser(Long userId) {
Session session = sessionFactory.openSession();
String hqlQuery = "from GrowBox where user_id =: userId";
Query query = session.createQuery(hqlQuery);
List growBoxes = query.getResultList();
session.flush();
session.close();
return growBoxes;
}
A HQL query would be
String hqlQuery = "from GrowBox gb where gb.responsibleUser.id =: userId";
Related
I have an entity like Process, which will be created by , updated by one user. When I try to apply the filter. I have created the foreign key relationship in the database. Now, when I use the JPA Specification to apply dynamic filter, I am getting exception as
No property CREATED found for type Process!
#Table(name = "process")
#Entity
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROCESS_ID")
#JsonProperty("id")
private Long id = null;
#NotNull
#Column(name = "NAME")
#JsonProperty("name")
private String name = null;
#Column(name = "CREATED_BY", updatable = false)
#JsonProperty("createdBy")
private Long createdBy = null;
#Column(name = "updatedBy", nullable = true)
#JsonProperty("updatedBy")
private Long updatedBy = null;
}
Hence, I Added the entity relationship mapping in the process entity as given below,
Now, I am getting below error. I am new to JPA and hibernate, the relation mapping is very confusing, kindly help.
#Table(name = "process")
#Entity
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROCESS_ID")
#JsonProperty("id")
private Long id = null;
#NotNull
#Column(name = "NAME")
#JsonProperty("name")
private String name = null;
#Column(name = "CREATED_BY", updatable = false)
#JsonProperty("createdBy")
private Long createdBy = null;
#Column(name = "updatedBy", nullable = true)
#JsonProperty("updatedBy")
private Long updatedBy = null;
//newly added below properties so that there will be no error when fetching data
#OneToOne(targetEntity = UserDetails.class, fetch = FetchType.LAZY, mappedBy = "id")
private UserDetails CREATED;
#OneToOne(targetEntity = UserDetails.class, fetch = FetchType.LAZY, mappedBy = "id")
private UserDetails UPDATED;
}
Now, I am getting the below error
Referenced property not a (One|Many)ToOne: com.app.users.details.domain.UserDetails.id in mappedBy of com.app.scenarios.domain.Process.CREATED
Kindly let me know what i am doing wrong. I have a process which can be created by a user and can be updated by a user. In DB, I am having a foreign key relationship for process and userdetails entity.
EDIT
Code to get the filtered data from DB using JPA Specification
Page<process> result = this.processDao.findAll(getprocessGridData(processSearchCondition.getprocessName()), pageRequest);
private static Specification<process> getprocessGridData(String processName) {
return (Specification<process>) (root, query, criteriaBuilder) -> (
criteriaBuilder.like(root.get("name"), processName)
);
}
I guess what you actually want is this:
#Table(name = "process")
#Entity
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROCESS_ID")
#JsonProperty("id")
private Long id;
#NotNull
#Column(name = "NAME")
#JsonProperty("name")
private String name;
#OneToOne(fetch = FetchType.LAZY)
#jOINColumn(name = "CREATED_BY", updatable = false)
private UserDetails createdBy;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "UPDATED_BY", nullable = true)
private UserDetails updatedBy;
}
I am new to hibernate/spring data JPA and occuring some problems when dealing with Foreign Keys.
I have the two table:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false)
private String name;
#Column(nullable = false)
private String email;
#Column(nullable = false)
private String password;
#Column(nullable = false)
private String role;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "job_id", referencedColumnName = "id")
private Job job;
}
#Entity
public class Job{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false)
private String name;
#OneToMany(
mappedBy = "job",
cascade = CascadeType.PERSIST,
fetch = FetchType.EAGER
)
private Set<User> users = new HashSet<>();
}
I am trying to save one Job (job.Id) at the Users table. But if I am trying to peform a get(repository.getOne(id)) (via ...extends JPARepository<User,Long> I am getting the following error:
org.hibernate.LazyInitializationException: could not initialize proxy [backend.entity.User#193] - no Session
Does anyone has a Tip how to fix it? I have read a lot on stackoverflow, but could not find out how to fix that.
Below - parent table - users:
#Entity
#Table(name = "user")
public class User {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "username", length = 50, unique = true)
#NotNull
#Size(min = 4, max = 50)
private String username;
#Column(name = "password", length = 100)
#NotNull
#Size(min = 4, max = 100)
private String password;
#ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
#JoinTable(
name = "user_role",
joinColumns = {#JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {#JoinColumn(name = "role_id", referencedColumnName = "id")})
private List<Role> roles;
//constructor, getters/setters
Below You can find table with roles:
#Entity
#Table(name = "role")
public class Role {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name", length = 50)
#NotNull
#Enumerated(EnumType.STRING)
private RoleName name;
#ManyToMany(mappedBy = "roles", fetch = FetchType.LAZY)
private List<User> users;
//constructor, getters/setters
And I will try save User by belows method:
private static SessionFactory sessionFactory;
private Session session;
#Override
public void saveUser(User user) {
Role role = getRoleByName(RoleName.ROLE_ADMIN);
user.getRoles().add(role );
role.getUsers().add( user );
session.persist(user);
}
public Role getRoleByName(RoleName name) {
Query query = session.createQuery("SELECT r FROM Role r WHERE r.name= :name");
query.setParameter("name", name);
return (Role) query.uniqueResult();
}
But I have two problems:
- first - the main problem - I did something wrong and I can't save new user.
- second one - I have null result in quer result in getRoleByName, but of course, that role exists in table user_roles.
And any solution will be perfect for me.
Thank you in advance.
I have two tables(entities):
#Entity
#Table(name = "users")
#NamedQuery(name = "User.getAll", query = "SELECT c from User c")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#NotNull
#Column(name = "LOGIN")
private String login;
#Column(name = "PASSWORD", length = 64)
private String password;
#Column(name = "SALT", length = 80)
private String salt;
#ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private Set<Role> roles;
#OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Permission> permissions;
And
#Entity
#Table(name = "roles")
#NamedQuery(name = "Role.getAll", query = "SELECT c from Role c")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Column(name = "ROLE_NAME", length = 100)
private String roleName;
#ManyToMany(mappedBy = "roles")
private Set<User> users;
And method for select Users:
#Override
public List<User> getUsersList() {
Criteria criteria = getSession().createCriteria(User.class);
return (List<User>)criteria.list();
}
I have 2 users. First user has 2 roles and second user has 1 role.
But this method return me 3 users. User who has 2 role is dublicate.
Itried criteria.createCriteria("", JoinType.NONE);
but it not helped.
You need to use criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY), check:
criteria-distinct-root-entity-vs-projections-distinct
I write my first java application to read rss stream and use spring, spring-data, hibernate.
My models.
RssFeed:
#Entity(name = "RssFeed")
#Table(name = "FEED")
#JsonIgnoreProperties({"rssChannel"})
public class RssFeed {
#Id
#GeneratedValue
#Column
private Integer id;
#Column(unique = true)
#Index(name = "title_index")
private String title;
#Column
#URL
private String link;
#Column
private String description;
#Column
private String content;
#Column
#Temporal(TemporalType.TIMESTAMP)
private Date pubDate;
#Column
#Temporal(TemporalType.TIMESTAMP)
private Date updateDate;
#ManyToOne
#JoinColumn(name = "channelId")
private RssChannel rssChannel;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "feed_category",
joinColumns = {#JoinColumn(name = "feed_id", nullable = false, updatable = false)},
inverseJoinColumns = {#JoinColumn(name = "category_id", nullable = false, updatable = false)})
private Set<RssCategory> rssCategories = new LinkedHashSet<RssCategory>();
}
RssChannel:
#Entity(name = "RssChannel")
#Table(name = "Channel",
uniqueConstraints = #UniqueConstraint(columnNames = {"link"}))
#JsonIgnoreProperties({"feeds"})
public class RssChannel implements Serializable{
#Id
#GeneratedValue
#Column
private Integer id;
#Column
private String title;
#Column(unique = true)
#org.hibernate.validator.constraints.URL
private String link;
#Column
#org.hibernate.validator.constraints.URL
private String image;
#Column
private String description;
#OneToMany(mappedBy = "rssChannel", cascade = CascadeType.ALL, orphanRemoval = true)
private List<RssFeed> feeds = new LinkedList<RssFeed>();
}
And RssCategory:
#Entity(name = "RssCategory")
#Table(name = "CATEGORY")
#JsonIgnoreProperties({"rssFeeds"})
public class RssCategory {
#Id
#GeneratedValue
#Column
private Integer id;
#Column(unique = true)
private String title;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "rssCategories")
public Set<RssFeed> rssFeeds = new LinkedHashSet<RssFeed>();
}
I use CrudRepository for manipulation with data. When save RssFeed without many to many it`s ok:
RssChannel channel = rssChannelService.get(url.toString());
rssFeed.setRssChannel(channel);
rssFeedService.save(rssFeed);
But when i add RssCategory:
rssCategory rssCategory = rssCategoryService.findOrCreate("test");
rssFeed.getRssCategories().add(rssCategory);
rssFeedService.save(rssFeed);
get exception: rg.hibernate.PersistentObjectException: detached entity passed to persist: RssCategory.
My RssFeedServiceImpl:
#Service
public class RssFeedServiceImpl implements RssFeedService {
#Autowired
private RssChannelDAO rssChannelDAO;
#Autowired
private RssFeedDAO rssFeedDAO;
#Override
public Page<RssFeed> findAll(Pageable pageable) {
return rssFeedDAO.findAll(pageable);
}
#Override
public Page<RssFeed> findAll(int rssChannelId, Pageable pageable) {
RssChannel rssChannel = rssChannelDAO.findOne(rssChannelId);
return rssFeedDAO.findByRssChannel(rssChannel, pageable);
}
#Override
public RssFeed get(String title) {
return rssFeedDAO.findByTitle(title);
}
#Override
public RssFeed save(RssFeed rssFeed) {
return rssFeedDAO.save(rssFeed);
}
}
And RssCategoryServiceImpl:
#Service
public class RssCategoryServiceImpl implements RssCategoryService {
#Autowired
RssCategoryDAO rssCategoryDAO;
#Override
public RssCategory findOrCreate(String title) {
RssCategory category = rssCategoryDAO.findByTitle(title);
if (category == null) {
category = new RssCategory();
category.setTitle(title);
category = rssCategoryDAO.save(category);
}
return category;
}
}
How save many to many?
You probably need to save your RssCategory first, in order to have an ID to store in feed_category table. This last save will be automatically made when you make the assignment:
rssFeed.getRssCategories().add(rssCategory);
but first you need to do:
rssFeedService.save(rssCategory);
Probably you'll need to put this operations within a transaction.