Set<T> within a Map<K,V> in Java - java

I was wondering if it is possible to have a Set member added as a member variable of a class, the object of which can then be put as a value into a Map.
My idea is to use HashSet<T> projects as a member variable for my employee class. But, I would like to have a query performed on a database that will return query results as a Map> item where int will be the employeeId and Set will be the projects. is it doable at all?

This is definitely doable. It looks like you are implementing a many-to-many relationship between employees and projects. This would correspond to a pair of tables with a junction table to connect them.
Your would read your employees and your projects, and then add projects to each employee set.
I should mention that it's not a good idea to expose a set as a member variable, because sets are mutable. You could make the variable private, and expose methods to add/query projects from your object.

Try something like this
class Project{
int pid;
int name;
//Getter and setter
}
Create Employee class
public class Employee {
int employeeId;
String name;
Set<Project> projects;
//getter , setter or add methods
}
Now you can use above two classes in DAO
public class EmployeesDao{
/* Get multiple employee-projects */
public Map<Integer, Set<Project>> getManyEmployeeAndProjects(){
Map<Integer, Set<Project>> emps = new HashMap<Integer, Set<Project>>();
//query and populate
return emps;
}
/**
* Get single employee
*/
public Employee getEmployee(){
//Query and return Employee
return new Employee();
}
}
That being said, I think you may only need return list of employees because Employee will have employee id and projects
public List<Employee> getEmployees(){
//create list of Employee object
}

Related

ArrayList getter and setter in a class java

public class Employee
{
private String name;
private String department;
private ArrayList<Employee>job= new ArrayList();
// just want to add getter and setter for this ArrayList
public void setJob(Employee j)
{
job.add(j);
// this is my setter
I want to be able to add later on as many 'job' as I want by extending the arraylist
While you can have setters and getter of List type, you should think carefully about their implementation, because most lists are mutable.
For instance, assume that you want to validate that the jobs list is not empty.
public void setJob(List<Employee> jobs) {
if (jobs.isEmpty()) throw new RuntimeException();
this.job = jobs;
}
Now the following code produces an employee without jobs:
Employee e = ...;
e.setJobs(jobs);
jobs.clear();
//the employee now has no jobs :-(
You can avoid this issue by making a defensive copy
public void setJob(List<Employee> j) {
this.job = new ArrayList<>(j);
}
The same applies to the getter. If you implement it as:
public List<Employee> getJobs() {
return this.jobs;
}
you are allowing the caller to modify the private job list without invoking the corresponding setter: myEmployee.getJobs().clear().
In this case, you may return an unmodifiable list instead of returning the inner object.
public List<Employee> getJobs() {
return java.util.Collections.unmodifiableList(this.jobs);
}
Ordinarily for a collection or array you would use addJob, removeJob and getJobs instead of a get/set pair.

Hibernate sort based on enum

I have am working a project which uses enums as columns to a database
public enum MyEnum{
a1(1,"act1"),
a2(2,"act2"),
a3(3,"act3"),
b1(4,"bob1"),
c1(10,"cake1"),
c2(11,"cake2"),
}
#Entity
public class MyEntity{
..
private Integer myEnumIntValue;
...
}
(NOTE: myEnumIntValue is not mapped as enum in the entity)
I have a hibernate query to query MyEntity. The query orders the result based on the int value of the enum
createCriteria(MyEntity.class).addOrder("myEnumIntValue");
This was all good until the enum was changed to
Public enum MyEnum{
a1(1,"act1"),
a2(2,"act2"),
a3(3,"act3"),
a4(7,"act4"),
b1(4,"bob1"),
c1(10,"cake1"),
c2(11,"cake2")
}
It now becomes a problem because the order of the result is i am getting is (a1,a2,a3,**b1,a4**,c1,c2) but sorting of the Entities should be (a1,a2,a3,**a4,b1**,c1,c2)
What is strategy can i use to resolve this?
If you don't want / can't manipulate the query to order the enums while fetching, remember that all enums implement the Comparable interface.
You can override the compareTo() method and do the sorting direclty from your java code.
To get specific:
public enum MyEnum{
a1(1,"act1"),
a2(2,"act2"),
a3(3,"act3"),
b1(4,"bob1"),
c1(10,"cake1"),
c2(11,"cake2");
private number;
private name;
public MyEnum(Integer number, String name){
this.number = number;
this.name = name;
}
//getters and setters
#Override
public int compareTo(MyEnum otherEnum){
return this.getName().compareTo(otherEnum.getName());
}
}
As soon as you have your List<MyEnum> myList fetched from the DB, you only have to call:
Collections.sort(myList);
to get your enums sorted via name.

Can I use POJO in Hibernate Filter?

Can I use Hibernate like this?
public class Employee{
private String name;
private String age;
//public getters and setters
}
public class EmployeeDao{
public List<Employee> getByFilter(Employee filter){
//what whould I write here?
}
}
public class Test{
public static void main(String[] args){
Employee employeeFilter = new Employee();
employeeFilter.setAge(15);
List<Employee> employeesOf15 = new EmployeeDao().getByFilter(employeeFilter);
}
}
If yes then how?
Yes, in your getByFilter() method, you could write a straightforward HQL or native SQL query to find all the employees who have an age equal to the filter's age, or use Hibernate's Criteria Queries like for example:
return getSession().createCriteria(Employee.class).add(Restrictions.eq("age", filter.getAge())).list();
It might be a good idea to add another parameter to your all-purpose getByFilter() method so you can specify filtering by any field (name, age, and so on), and then act accordingly.

Aggregation with 1:m between objects

I have member.objects that are painters, carpenters and TeamLeads which can have other TeamLeads, painters or carpenters under them. Is there a way to connect them so that I can getTeamLeads.team and also have the ability to see who is working under their TeamLeads.team. I understand how to do it with a database but wanted to see if composition or aggregation would handle a 1:m relationship and if there is an example somewhere that I could see. Would it require maybe a Team.class to link everyone or can it be handled by local references and I just can't find any examples.
As i see it you can do this with a private collection that can be managed by modifiers which also mantain reverse relationship something like this:
public class TeamMember {
private TeamMember leader;
private Set<TeamMember> teamMembers= new HashSet<TeamMember>();
public Set<TeamMember> getTeamMembers(){
return new HashSet<TeamMember>(teamMembers);
}
public void addTeamMember(TeamMember member){
if(member.leader!=null){
member.leader.removeTeamMember(member);
}
member.leader=this;
teamMembers.add(member);
}
public void removeTeamMember(TeamMember member){
member.leader=null;
teamMembers.remove(member);
}
public TeamMember getLeader(){
return leader;
}
}
Since you dont have public setters for teamMembers or leader the only way to change leader or teamMembers is by using the addTeamMember and removeTeamMember methods so you have the bidirectional relationship mantained by these methods.
I wish this may help.
So it sounds like you have some a method with this sort of signature to retrieve the list of TeamLead:
public List<TeamLead> getTeamLeads()
And from there, you want to get the members of each team, your TeamLead class would look something like this:
public class TeamLead {
private final List<Person> team = new ArrayList<Person> ();
// You can of course populate this list however is best for your code
public void addTeamMember(Person p) {
team.add(p);
}
public List<Person> getTeam() {
return team;
}
// more code...
}
Where Person is the base class for Painter, Carpenter, and TeamLead - there are other ways to do this without a class hierarchy, but I'll stick to this for easier explanation for now.

Linkend List copy constructor

I am having problems with the copy constructor of a Linkend List in Java.
The list I am trying to copy has a size of 3, when I use the copy constructor the list is empty.
When I try this with the clone method everything works great.
I have look a this for a quite a while and I get the feeling it is so obvious. I just
dont see it, here is the code.
public class Employee {
private String name;
private double salary;
public Employee(String name, double salary){
this.name = name;
this.salary = salary;
}
public void setname(String name){
this.name = name;
}
public void setsalary(double salary){
this.salary = salary;
}
public String getname(){
return this.name;
}
public double getsalary(){
return this.salary;
}
}
public class Main {
public static void main(String[] args) {
Employees employees = new Employees();
employees.add(new Employee("Employee1", 2500.00));
employees.add(new Employee("Employee2", 2400.00));
employees.add(new Employee("Employee3", 2000.00));
Employees employeesCopy2 = new Employees(employees);
Employees employeesCopy = (Employees) employees.clone();
System.out.println(employees.size());
System.out.println(employeesCopy2.size());
System.out.println(employeesCopy.size());
}
}
import java.util.LinkedList;
public class Employees extends LinkedList<Employee> {
private static final long serialVersionUID = 1L;
private LinkedList<Employee> employees;
public Employees(){
employees = new LinkedList<Employee>();
}
public Employees(Employees w){
employees = new LinkedList<Employee>(w);
}
public void addWerknemer(Employee w){
employees.add(w);
}
}
EDIT
This is homework, but when I wanted to add the tag is showed that the tag was no longer is use.
I think this:
public class Employees extends LinkedList<Employee> {
private LinkedList<Employee> employees;
will create a world of confusion. You're both extending a list, and within that class you're maintaining a separate list. When you call addWerknemer() you add to the inner list. What happens when you call get() ? Since you've not overridden this, you're calling get() on the base class, and that's a different list!
Without inspecting the rest of your code, I suspect this is a fundamental source of problems.
You have two choices:
Employees extends List
Employees contains a List
I would prefer the second. You can change the underlying collection (e.g. a Set, perhaps a Map for better lookup performance) and not change the exposed interface.
You are extending LinkedList, but also have a LinkedList inside that extension. Initially you use the add method to add Employee instances, so they get added to the Employees list itself, but when you use the copy constructor, you copy those employees to the employees field inside your Employees class.
When you call the size() method, it will use the LinkedList of the Employees object itself, so in the first list it is 3, but on the second it is 0 as now the employees are in the contained list and not in the object itself.
In this case you probably should not extend LinkedList. Or if you do, then don't use a separate field like employees which also contains a LinkedList.
Your confusion comes from the fact, that Employees both is a list and contains a list. When you use
employees.add(new Employee("Employee1", 2500.00));
you add the employee to the outer list. When you use
employees.addWerknemer(new Employee("Employee1", 2500.00));
you add the employee to the inner list. Since you have overwritten the constructor Employees(Employees es), this will not clone the outer list, but only the inner. And since you haven't overwritten clone(), it will clone the outer list, but not the inner. This is rather messy and also most probably not intended by you. I therefore propose one of the following changes:
1. [Preferred] Employees only contains a list and not extends one
Skip the extends LinkedList<Employee> and only work with an internal list. You will have to use your method addWerknemer(Employee emp) to add to your list (or change it's name to add). You will have to implement size and clone as well as other methods that you wish to use. If you want to be really clean about this, you can even make the class implement List or implement Collection or so. This way you can still treat your class as a java.util.Collection. I don't think that this would be neccessary in your case though. Also you would need to implement all of the interfaces methods (there are many). An example implementation would look like this. You still have to implement size, etc.
public class Employees /*implements List<Employees>*/ {
private static final long serialVersionUID = 1L;
private LinkedList<Employee> employees;
public Employees(){
employees = new LinkedList<Employee>();
}
public Employees(Employees w){
employees = new LinkedList<Employee>(w);
}
public void add(Employee w){
employees.add(w);
}
public Employees clone() {
return employees.clone();
}
// add more methods as you need them (like remove, get, size, etc)
}
2. Employees only extends LinkedList and doesn't contain one
Throw away your methods addWerknemer(Employee emp) and the copy constructor Employees(Employees) as well as your internal list. This way you will not overwrite the existing implementations of LinkedList. This approach is more or less useless because you basically just rename LinkedList to Employees and add/change nothing. Therefore I wouldn't recommend this approach.

Categories

Resources