Why ResponseEntity calls hibernate while lazy loading active - java

Below is the DAO. I am getting the first UppeningUsers object. Note that here for this function I do not want to return peopleWhoBlockedMe set which is located inside the UppeningUsers..
But in different functions I would like to return that information. Note that Both of them are LAZY fetching. With evict I tried to detach the object but still it did not work.
First of all RESTcontroller is below. Then the DAO code is below. Then two entity descriptions are below.
Question is: I see that until
return new ResponseEntity(returned, HttpStatus.OK);
There is only one query which is the typical select. I do not want hibernate to go and take also UserBlock information of that specific UppeningUser. Because it is not needed for this service response. However even though it is lazy loading for some reason
return new ResponseEntity(returned, HttpStatus.OK);
calls the hibernate. I dont know why in restcontroller still it is connected to the database. I tried evict but didnt work.
The json response is
{"id":7,"peopleWhoBlockedMe":[{"blockedId":7}]}
But I do not want for this function to return this peopleWhoBlockedMe. It can be empty.
PLEASE NOTE that in other service for example I will explictly request this peopleWhoBlockedMe but just for this business logic I do not need this information. So what I can do to prevent this so whenever I actually want to call peopleWhoBlockedMe I can get it. Not automaticly.
#RestController
public class TempController {
#Autowired
UppeningUsersService uppeningUsersService;
#RequestMapping(value = "/testing", method = RequestMethod.GET)
public ResponseEntity<UppeningUsers> getPhotos() {
try {
UppeningUsers returned = uppeningUsersService.getUsersDetailsPartial();
return new ResponseEntity<UppeningUsers>(returned, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
This part is the DAO.
#Repository
public class UppeningUsersDAO {
#Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf) {
this.sessionFactory = sf;
}
/**
* Get Existing user. Return error if there is not.
* #param incomingUser user who requested access.
* #return returns the guy information. All information.
*/
#Transactional
public UppeningUsers getUserDetails() throws Exception {
Session session = this.sessionFactory.getCurrentSession();
Query query = session.createQuery("from UppeningUsers ");
UppeningUsers returning = (UppeningUsers) query.list().get(0);
session.evict(returning);
return returning;
}
}
The main table is this one..
#Entity
#Table(name = "uppening_users")
#Proxy(lazy = true)
public class UppeningUsers {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private
int id;
#OneToMany(mappedBy = "blockedId",cascade =CascadeType.ALL, fetch = FetchType.LAZY)
private Set<UserBlocks> peopleWhoBlockedMe;
public UppeningUsers() {
super();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Set<UserBlocks> getPeopleWhoBlockedMe() {
return peopleWhoBlockedMe;
}
public void setPeopleWhoBlockedMe(Set<UserBlocks> peopleWhoBlockedMes) {
this.peopleWhoBlockedMe = peopleWhoBlockedMes;
}
}
Now here is the other table.
#Entity
#Table(name="user_blocks")
#Proxy(lazy = true)
public class UserBlocks {
#Id
#Column(name="id")
#GeneratedValue(strategy= GenerationType.IDENTITY)
int id;
#Column(name = "blocked_id",insertable = false,updatable = false)
private int blockedId;
public int getBlockedId() {
return blockedId;
}
public void setBlockedId(int blockedId) {
this.blockedId = blockedId;
}
}
UPDATE: 2 forgot to add the service
#Service("uppeningUserService")
public class UppeningUsersService {
#Autowired
UppeningUsersDAO uppeningUsersDAO;
public UppeningUsers getUsersDetailsPartial( ) throws Exception {
return uppeningUsersDAO.getUserDetails();
}
}

Jens is right about her sentence. The layer methodology and writing business objects fix the issue. Thank you.

Related

JPA createQuery where condition does not work

I am trying to use JPA to fetch records from database. However I am able to insert records indatabse and even get all the records using createQuery method of class EntityManager.
But in below case I am not getting why the condition in where clause is not working.
Please help me figure it out.
POJO class :
#Entity
#Table(name = "frameworks_filter")
public class FilteredFrameworksDbStructure {
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "regular_name")
private String regularName;
#Column(name = "component_name")
private String componentName;
#Column(name = "component_owner")
private String componentOwner;
#Column(name = "frameworks")
private String frameworks;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRegularName() {
return regularName;
}
public void setRegularName(String regularName) {
this.regularName = regularName;
}
public String getComponentName() {
return componentName;
}
public void setComponentName(String componentName) {
this.componentName = componentName;
}
public String getComponentOwner() {
return componentOwner;
}
public void setComponentOwner(String componentOwner) {
this.componentOwner = componentOwner;
}
public String getFrameworks() {
return frameworks;
}
public void setFrameworks(String frameworks) {
this.frameworks = frameworks;
}
}
DAO class method:
public List<FilteredFrameworksDbStructure> getFilteredFrameworks(String regularName) {
EntityManager entityManager = entityManagerFactory.createEntityManager();
List<FilteredFrameworksDbStructure> filteredFrameworksDbStructureList = entityManager
.createQuery("from FilteredFrameworksDbStructure F where F.regularName = :regular", FilteredFrameworksDbStructure.class)
.setParameter("regular", regularName)
.getResultList();
return filteredFrameworksDbStructureList;
}
Issue : Condition in where clause does not work. It simply fetch all the records irrespective of the regularName provided.
Regards,
Parag Vinchurkar
Why don't you use the JpaRepository or CrudRepository to fetch your results? Check out this tutorial here and here on how to use them.
And you can use your where clause. Please see below the example repository you can use to obtain the same results as the entityManager
public interface FilteredFrameworksDbStructureRepo extends JpaRepository<FilteredFrameworksDbStructure , Integer>{
List<FilteredFrameworksDbStructure> findAllByRegularName(String regularName)
}
Please note that you will have to change your id member variable from int to Integer

Hibernate with mysql overwrites pk

Well, I'm using Hibernate for the first time and, unexpectedly, it works. Except for one thing: an insert with a pk already inserted overwrite the record instaed of preventing it.
That's my simple code:
#Controller
public class SimpleController {
#Autowired
UserRepository userRepository;
#GetMapping("/mainPage")
public String viewMainPage(){
return "mainPage";
}
#GetMapping("/nuovo-utente")
public String viewInserisciUtente(Model model){
model.addAttribute("nuovoUtente", new Utente());
return "nuovo-utente";
}
#PostMapping("/nuovo-utente")
public String memorizzaUtente(#ModelAttribute Utente utente){
userRepository.save(utente);
return "output";
}
}
#Entity
public class Utente {
#Id
private int id;
private String citta=null;
private String genere=null;
private String data_nascita=null;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCitta() {
return citta;
}
public void setCitta(String citta) {
this.citta = citta;
}
public String getGenere() {
return genere;
}
public void setGenere(String genere) {
this.genere = genere;
}
public String getData_nascita() {
return data_nascita;
}
public void setData_nascita(String data_nascita) {
this.data_nascita = data_nascita;
}
}
Any help will be appreciated.
EDIT: I've added the entity class to help you understanding my problem. Hoping that this will help.
Thanks you all
If you look at CrudRepository documentation, then we don't have update method, but we only have save method, which is used to add or update existing records.
In your case, you might have updated an entity (except its Id field) and tried saving the entity. So, CrudRepository will update the existing value for given Id, since it is already present.
Try adding ID generation strategy to id field.
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

Hibernate: Getting result using a specific field

I've been following a lot of tutorial on how to get a list of result by referencing a specific column in the table.
I have this table.
I want to get the list of result with a plan_code "TEST123"
This is my code:
PlanRepository.java
public interface PlanCoverageRepository extends CrudRepository<PlanCoverage, Long> {
List<PlanCoverage> findAllByPlan_code(String plan_code);
}
PlanCoverageService.java
public interface PlanCoverageService {
public List<PlanCoverage> getAllPlanCoverageByPlanCode(String plan_code);
}
PlanCoverageServiceImpl.java
#Service
#Transactional
public class PlanCoverageServiceImpl implements PlanCoverageService {
#Override
public List<PlanCoverage> getAllPlanCoverageByPlanCode(String plan_code) {
return (List<PlanCoverage>) planCoverageRepository.findAllByPlan_code(plan_code);
}
}
PlanCoverageController.java
#Controller
#RequestMapping(value="/admin")
public class PlanCoverageController {
#Autowired
PlanCoverageService planCoverageService;
#RequestMapping(value="/Test/{plan_code}", method=RequestMethod.GET)
public ModelAndView test(#PathVariable String plan_code) {
ModelAndView model = new ModelAndView();
PlanCoverage planCoverage = (PlanCoverage) planCoverageService.getAllPlanCoverageByPlanCode(plan_code);
model.addObject("planCoverageForm",planCoverage);
model.setViewName("plan_coverage_form");
return model;
}
}
PlanCoverage.java
#Entity
#Table(name="plan_coverage")
public class PlanCoverage {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private long coverage_id;
#Column(name="plan_code")
private String plan_code;
#Column(name="coverage_description")
private String coverage_description;
/..getters and setters
#ManyToOne()
#JoinColumn(name="plan_code", referencedColumnName = "plan_code",insertable=false, updatable=false)
private Plan plan;
public Plan getPlan() {
return plan;
}
public void setPlan(Plan plan) {
this.plan = plan;
}
}
Please help me. I've been stuck with these for a few days and non of the tutorials seems to work on me. Thank you so much!!
You have messed up with the convention that spring boot is using to compose query methods. The case of the fields in the entity should follow the lower camel-case scheme, like so:
#Column(name="plan_code")
private String planCode;
and then the query method in PlanCoverageRepository should be:
List<PlanCoverage> findAllByPlanCode(String planCode);

JPA - delete entry from reference table

I implemented a workbench permission system with groups and permissions.
A reference table workbench_group_permissions_reference has references so I can easily add and remove permissions to a group.
Adding a new reference entry works fine, but removing does not. I do not get any error, but the reference still exists in the database after removal. I am using postgreSQL.
Here is my reference class:
#XmlRootElement
#Entity
#Table(name = "workbench_group_permissions_reference", uniqueConstraints = {
#UniqueConstraint(columnNames = { "workbenchgroupspermissions_id", "workbench_groups_id" }) })
public class WorkbenchGroupPermissionReferenceEntity extends BasicEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#ManyToOne
#JoinColumn(name = "workbenchgroupspermissions_id")
private WorkbenchPermissionEntity workbenchPermission;
#ManyToOne
#JoinColumn(name = "workbench_groups_id")
private WorkbenchGroupEntity workbenchGroup;
/**
* Empty constructor to make JPA happy.
*/
public WorkbenchGroupPermissionReferenceEntity() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public WorkbenchPermissionEntity getWorkbenchPermission() {
return workbenchPermission;
}
public void setWorkbenchPermission(WorkbenchPermissionEntity workbenchPermission) {
this.workbenchPermission = workbenchPermission;
}
public WorkbenchGroupEntity getWorkbenchGroup() {
return workbenchGroup;
}
public void setWorkbenchGroup(WorkbenchGroupEntity workbenchGroup) {
this.workbenchGroup = workbenchGroup;
}
}
This is my remove method:
public void deleteWorkbenchGroupPermission(final WorkbenchGroupPermissionReferenceEntity workbenchGroupPermission) {
long id = workbenchGroupPermission.getId();
super.delete(WorkbenchGroupPermissionReferenceEntity.class, id);
}
And the super.delete method:
protected void delete(final Class<?> type, final Object id) {
Object ref = this.em.getReference(type, id);
this.em.remove(ref);
}
What am I missing here?
The link in the comment of Dragan was pointing me to the right direction.
I tried to delete the reference, but the owning entity (WorkbenchGroupEntity) still had the reference.
What I did to solve the problem was to first remove the reference from the owning entity and then remove the cross-reference entity afterwards:
WorkbenchGroupPermissionReferenceEntity permissionToRemove = new WorkbenchGroupPermissionReferenceEntity();
for(WorkbenchGroupPermissionReferenceEntity permissionReference : existingGroupPermissions) {
Long permissionRefernceId = permissionReference.getId();
if(permissionRefernceId.equals(permissionId)){
permissionToRemove = permissionReference;
} else {
newGroupPermissions.add(permissionReference);
}
}
workbenchGroupEntity.setWorkbenchGroupPermissions(newGroupPermissions);
workbenchGroupControl.updateWorkbenchGroup(workbenchGroupEntity);
workbenchGroupPermissionsControl.deleteWorkbenchGroupPermission(permissionToRemove);
EDIT:
As the solution mentioned above was the main reason for the delete not working properly, I made another stupid mistake: I was comparing the id of the cross reference entity to the id of the permission id instead of the permission id itself, so the reference was never found.
Updated check:
for (WorkbenchGroupPermissionReferenceEntity permissionReference : existingGroupPermissions) {
// here was the mistake
Long permissionReferenceId = permissionReference.getWorkbenchPermission().getId();
if (permissionReferenceId.equals(permissionId)) {
permissionToRemove = permissionReference;
} else {
newGroupPermissions.add(permissionReference);
}
}

How to set true or false if there is no record in table using hibernate

I am using Spring REST with Hibernate and i am fetching a particular record from database table passing id into my method. The method is working properly but if there is no record in table then i want false in a variable and if record exist then i want true in the variable in my json object.
Here is my Entity class Subscribe.java
#Entity
#Table(name="subscribe")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Subscribe implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name="id")
private long id;
#Column(name="subscribed_id")
private String subID;
#Column(name="subscriber_id")
private long subrID;
public long getSubrID() {
return subrID;
}
public void setSubrID(long subrID) {
this.subrID = subrID;
}
public String getSubID() {
return subID;
}
public void setSubID(String subID) {
this.subID = subID;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
Here is my DAO class
#SuppressWarnings({ "unchecked", "rawtypes" })
public List<Subscribe> getSubscribeById(long id) throws Exception {
session = sessionFactory.openSession();
Criteria cr = session.createCriteria(Subscribe.class);
cr.add(Restrictions.eq("subrID", id));
List results = cr.list();
tx = session.getTransaction();
session.beginTransaction();
tx.commit();
return results;
}
And here is my Controller
#RequestMapping(value = "/subscribe/{id}", method = RequestMethod.GET)
public #ResponseBody
List<Subscribe> getSubscriber(#PathVariable("id") long id) {
List<Subscribe> sub = null;
try {
sub = profileService.getSubscribeById(id);
} catch (Exception e) {
e.printStackTrace();
}
return sub;
}
Please suggest me how can can i do this
Given the way your code is structured ( where you effectively pass the database object directly to the REST client ) there is no clean way that you can do this.
I think a more RESTful approach would be to return an HTTP code that indicates that the requested record could not be found. HTTP 404 would be the appropriate code to use.
So, in pseudo-code,
#RequestMapping(value = "/subscribe/{id}", method = RequestMethod.GET)
public #ResponseBody
List<Subscribe> getSubscriber(#PathVariable("id") long id) {
List<Subscribe> sub = null;
try {
sub = profileService.getSubscribeById(id);
} catch (Exception e) {
e.printStackTrace();
}
if ( sub.isEmpty() ){
return HTTP 404 result code
} else {
return sub;
}
}
Your client side code will need to be altered to respond to the HTTP result code rather than a boolean value, but otherwise would remain unchanged.

Categories

Resources