I am new to Java and working in Employee management system . I have created few classes including Employee(name, dob etc), Department (dept name, description etc). I have a requirement that Department must have 2 empoyee and less than 10.
Can anyone tell me how to make that association?
Department class:
public class Department {
private String departmentName;
private String locationofDep;
Employee emp = new Employee()
Getter.. setter
}
public class Employee {
private String empName;
private String dob;
Getter.. setter
}
According to the question you should have a collection of Employee object. So you have to create Employee Collection such List, Set and etc. However you cannot limit the capacity a Collection such between two values. Programmatically only thing you can do is throw an Exception when calling the getter method of the Collection. You can put two default value to the Collection. I don't believe that would work for you. Do following modifications in your code.
public class Department {
private String departmentName;
private String locationofDep;
//collection of empleyees
Set<Employee> employees = new HashSet<>();
//use this method to add employees
public void addEmployee(Employee employee) {
this.employees.add(employee);;
}
public Set<Employee> getEmployees() throws Exception {
if (this.employees.size() < 2 || this.employees.size() > 10) {
throw new Exception("Employees out of capacity");
}
return this.employees;
}
//other getters and setters should be here
}
public class Employee {
private String empName;
private String dob;
//put getters and setters
}
So you can manage the employee length problem when you getting employee information using try-catch blocks
Related
Let's say I have a class in java called Employee that looks something like this
public class Employee {
private String empName;
private int empId;
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
}
Now I want to use this object in an immutable class let's say a company in the following format. and the condition is that I cannot modify
public final class Company {
final String companyName;
final Employee employee;
public Company(String companyName, Employee employee) {
this.companyName = companyName;
this.employee = employee;
}
public String getCompanyName() {
return companyName;
}
public Employee getEmployee() {
return employee;
}
}
So my question is, is this a valid way to make Company class immutable when I am referencing an inside object that can be modified?
As referenced in this article https://www.journaldev.com/129/how-to-create-immutable-class-in-java do a deep cloning of Employee object in your constructor of final class. This way you will won’t use the object reference.
2 things that came to my mind:
Add a ReadOnlyEmployee Interface for your Employee which only exposes the getters. Then you would have to change the return type of getEmployee() to ReadOnlyEmployee. The advantage of this solution is that it's clear and explicit for the user. The problem is that the getter returns another type than the constructor accepts which may be confusing.
Add a proxy class that extends the Employee class that throws an IllegalAccessException or similar on setter calls. The advantage is that you do not have to introduce new Interfaces or change the methods of Company. The disadvantage is the possible runtime Exceptions.
Technically, no. Adding final makes the reference immutable: you cannot assign a different Employee object. this.employee = ... is impossible.
However, finality isn't contagious the way constness is in C++. It's still possible to call getEmployee().setEmpName(...) or getEmployee().setEmpId(...) and modify the employee object. You can't replace it with a new one but you can modify the object that's there.
If you want to make Company completely immutable then you need to make defensive copies of the Employee object in two places. One, you need to copy the object passed in the constructor. Two, you need to return a copy from getEmployee() to prevent the internal object from being exposed.
public final class Company {
final String companyName;
final Employee employee;
public Company(String companyName, Employee employee) {
this.companyName = companyName;
this.employee = new Employee(employee); // 1
}
public String getCompanyName() {
return companyName;
}
public Employee getEmployee() {
return new Employee(employee); // 2
}
}
The problem is that you release a reference to an employee instance, thus the caller may modify the object.
You return a link to a copy of the employee and stop worrying about what will happen next. You protected the underlying instance. The caller can do whatever they want with a copy, while your field remains consistent and effectively unchanged (in fact, it's changeable, of course).
public class Employee {
public Employee(Employee o) {
// copy evething you need from o
}
}
public final class Company {
public Employee getEmployee() {
return new Employee(employee);
}
}
Problems here? The caller is altering the employee's data and can't figure out why nothing has been changed within the company.
You return a reference to a Company's inner subclass of Employee. In this class, you override setters and other methods that change the state. The caller, for instance, might be getting an UnsupportedOperationException when they call such modifying methods on a retrieved Employee.
public final class Company {
private final CompanyEmployee companyEmployee;
public Company(String companyName, Employee employee) {
this.companyName = companyName;
companyEmployee = new CompanyEmploye(employee);
}
private static class CompanyEmployee extends Employee {
public Employee(Employee o) {
super(o);
}
public void setEmpName(String empName) {
throw new UnsupportedOperationException();
}
public void setEmpId(int empId) {
throw new UnsupportedOperationException();
}
}
public Employee getEmployee() {
return companyEmployee;
}
}
Problems here? Inheritance is used to control access.
Otherwise, an immutable class that is made of mutable components isn't that immutable.
Is this a valid way to make Company class immutable when I am referencing an inside object that can be modified?
No. From my understanding, any component obtained from an instance of an immutable class shouldn't be alterable. No matter at what level a request to change may occur.
This is the code I wrote so far for the other things I need to do. The main problem is that even with so much info I can't understand how to do it.
Create a map from the farm list which has like key the salary and like value the list of employee that has that salary. Display the map content, and for each employee display the farm in which is working
public class Employee implements Comparable<Employee> {
private String name;
private Integer salary;
public Employee (String name , Integer salary) {
this.name = name;
this.salary = salary;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSalary(Integer salary) {
this.salary = salary;
}
public Integer getSalary() {
return salary;
}
public String toString() {
return name + " " + salary;
}
public int compareTo(Employee emp) {
return this.salary.compareTo(emp.getSalary());
}
}
Farm class
public class Farm {
private String name;
private Integer surface;
List<Employee> emp = new ArrayList<Employee>();
public Farm(String name , Integer surface) {
this.name = name;
this.surface = surface;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSurface(Integer surface) {
this.surface = surface;
}
public int getSurface () {
return surface;
}
public String toString() {
return name + " " + surface;
}
public void makeList(String ename , Integer esalary) {
this.emp.add(new Employee(ename,esalary));
}
public void getList() {
for(Employee el : emp)
System.out.println(el);
}
public Employee getMostPaidEmployee() {
return Collections.max(emp);
}
}
And my main one
public static void main(String args[])
{
List <Farm> FarmList = new ArrayList<Farm>();
Farm farm1 = new Farm("Tiguana" , 700);
farm1.makeList("Mihai", 30000);
farm1.makeList("Vladimir", 4000);
farm1.makeList("Tusnic", 3000);
farm1.getList();
System.out.println(farm1.getMostPaidEmployee());
Farm farm2 = new Farm("Tipirei" , 800);
farm2.makeList("Mihai", 30000);
farm2.makeList("Mihail", 40000);
farm2.makeList("Armando", 50000);
farm2.makeList("ASihai", 60000);
System.out.println(farm2.getMostPaidEmployee());
FarmList.add(farm2);
FarmList.add(farm1);
}
Map< Integer , List< Employee > >
Sounds like you want to build a Map< Integer , List< Employee > >. The key, of type Integer (object, not primitive int), is the salary. The value is a List of employees with that particular salary.
So you need to instantiate such a Map, probably a HashMap, or perhaps a SortedMap such as TreeMap. Then as you loop the employees, you see if their salary has already been added as a key to the map. If not, add the salary as a key, and create an empty List object as the value. Add that particular employee to the new list. If the salary is already present, retrieve the list, add the employee.
To report by farm, you need to find which farm hired that employee. You will loop the keys of the map, for each key retrieve its list of employees, and then loop those employees. For each employee, loop all the farms, and retrieve each farm’s list of employees, and see if the target employee is in that list. If so, you know the farm of the employee in the list on the map.
One flaw in your code is defining a compareTo on Employee by salary. Intuitively we can tell that does not smell right. You should instead have an identifier on each employee, like most any company assigns an “employee id” to each person hired. For the sake of your exercise, I would just use a UUID as the id. Add a member field of type UUID to your Employee class. Define compareTo using that object.
As this is obviously homework, I think I have said enough. You should be able to figure this out following my prose. You can also search Stack Overflow for many many examples of maps with a list as the value, and other such issues.
In real work, we would likely be concerned with concurrency issues. But I assume that was not intended as part of your school assignment.
See also the coding-style tips I posted as Comments on the Question.
This is how you gonna do it :
Map<Integer, List<Employee>> map = new HashMap<>();
for(Farm f : FarmList){
for(Employee e : f.emp){
if(!map.containsKey(e.salary)){
map.put(e.salary, new ArrayList<>());
}
map.get(e.salary).add(e);
}
}
Be sure to add the field of FarmName to your employee and override toString() method in Employee class so you can display what's asked.
I am new to objects and classes in java. I want to know how to get data from attribute objects. I have 4 classes
public class Personnel {
private ArrayList<Employee> employees = new ArrayList<Employee>();
public void addEmployee(Employee employee){
employees.add(employee);
}
public ArrayList<Employee> getEmployees() {
return this.employees;
}
}
public class Employee{
/**DATAFIELDS*/
private String name;
Address address;
PayInfo pay;
//Constructor
//methods
.....
}
public class PayInfo {
/**DATAFIELDS*/
private double salary;
private boolean isFullTime;
//Constructors
//Methods
....
}
public class Address {
/**DATAFIELDS*/
private String streetAddress;
private String city;
private String state;
private String zipCode;
//Constructors
//Methods
.....
}
I have created payInfo and address objects and added to the employee object. And finally added that employee object to the Personnel object and saved in an ArrayList. But my question is, whether is there any way to retrieve all these information from just Personnel object rather than going through each objects ? Thanks in advance !!
I mean i want something like this from my Main method,
public static void main(String[] args) {
//Create CODPersonnel Object
CODPersonnel personnelEmployee = new CODPersonnel();
//Address Object for emp1 Object
Address addressEmp1 = new Address();
addressEmp1.setStreetAddress("637 67th Place");
addressEmp1.setCity("Willowbrook");
addressEmp1.setState("IL");
addressEmp1.setZipCode("60527");
//PayInfo for emp1 object
PayInfo emp1PayInfo = new PayInfo();
emp1PayInfo.setFullTime(true);
emp1PayInfo.setSalary(85000.0);
//Create the Employee object
//and set attributes
Employee emp1 = new Employee();
emp1.setName("Samantha Simmons");
emp1.setAddress(addressEmp1);
emp1.setPay(emp1PayInfo);
//Add objects to CODPersonnel objects
personnelEmployee.addEmployee(emp1);
}
And i want to retrieve all information through Personnel object like,
System.out.println(personnelEmployee.getEmployees(......);
or,
System.out.println(personnelEmployee.getAddress.streetName..etc,) something like that. I know it may sound stupid but is there any way like that??
You could put PayInfo and Address into a Details class. Each Employee could be composed of a Details object. You can then access the Details object from the Personnel class:
class Personnel {
private Map<String, Employee> employees = new HashMap<>();
public void addEmployee(Employee employee) {
employees.put(employee.getName(), employee);
}
public Details getEmployeeDetails(String name) {
return employees.get(name).getDetails();
}
}
class Employee {
private String name; //could be stored in Details
private Details details;
public Employee(String name, Details details) {
this.details = details;
}
public Details getDetails() {
return details;
}
public String getName() {
return name;
}
}
class Details {
private PayInfo payInfo;
private Address address;
public Details(PayInfo payInfo, Address address) {
this.payInfo = payInfo;
this.address = address;
}
public PayInfo getPayInfo() {
return payInfo;
}
public Address getAddress() {
return address;
}
}
I switched your List into a Map, so you can easily access each employee by name. You could then do:
public static void main(String[] args) {
PayInfo info = ...;
Address address = ...;
Details details = new Details(info, address);
String name = ...
Employee employee = new Employee(name, details);
Personnel personnel = new Personnel();
personnel.addEmployee(employee);
//example
Details employeeDetails = personnel.getEmployeeDetails("Some Name");
Address employeeAddress = employeeDetails.getAddress();
System.out.println(employeeAddress.getStreetAddress());
}
This design strongly violates the Law of Demeter, so if you're looking for a design that doesn't violate it, I'll be more than happy to edit in a stronger design.
Not sure what you're asking. You can access the information from the Employee objects in the ArrayList in Personnel, assuming you have the appropriate getters and setters in Employee that returns its PayInfo and Address.
So I'm kinda curious how can I store for example a list of items in my class with prices, code, quantity and so on.
Is there an easy way to have it all related and not creating a function for each variable?
You can define a List object in your class.
For example a person that has credit cards:
public Class Person {
private String name;
private List<CreditCard> creditCards;
// toString, equals, constructor, etc.
public void setCreditCards(List<CreditCard> creditCards) {
this.creditCards = creditCards;
}
public List<Creditcard> getCreditCards() {
return this.creditCards;
}
// more getters and setters
And the Credit Card:
public Class CreditCard {
private String number;
private Date expiryDate;
// getters and setters
}
And then you can make calls like this:
Person person = new Person();
List<CreditCard> cards = person.getCreditCards();
for(CreditCard card: cards) {
String number = card.getNumber();
}
A Java class can be thought of as a collection of fields (variables), and methods (functions).
The way you make a class hold more than one piece of data is to add more fields, and more methods to access those fields.
For example:
public class Cat {
int id;
String name;
double price;
public Integer getId() {
return this.id;
}
//........etc
}
You can then store that in your list and access different bits of data.
I am exploring JPA and Ebean within Play Framework 2.0.1 to research what is generated in a local relational database. In my tests, I'm using MariaDB, a fork of MySQL.
So far, I've been able to successfully generate tables in the database using the JPA annotations within my models. I wanted to make sure that I learned how to set up an entity with a OneToOne relationship to another entitiy, as well as a OneToMany to another.
OneToOne: Employee has Address
OneToMany: Employee has Pet(s)
I set up a small application that allows me to quickly populate the tables, display some of the info, and delete rows from the tables. Here is the code below for those who want to see my setup:
Routes
GET / controllers.Application.index()
GET /add controllers.Application.addEmployee()
GET /delete/:id controllers.Application.deleteEmployee(id: Long)
GET /employee/:id controllers.Application.showEmployee(id: Long)
Controller
Application.java
public class Application extends Controller {
public static Result index() {
return ok(index.render("entry point"));
}
public static Result addEmployee() {
// Create an employee.
Employee employee = new Employee();
employee.firstName = "John";
employee.lastName = "Doe";
employee.salary = new BigDecimal(123456);
// Create an address for the employee.
Address address = new Address();
address.city = "West Chester";
address.country = "United States of America";
address.postalCode = "19380";
address.province = null;
address.street = "45 Jingleheimer Drive";
// Create pets for the employee.
Pet pet = new Pet();
pet.petString = "dog";
Pet pet2 = new Pet();
pet2.petString = "cat";
employee.address = address;
employee.pets.add(pet);
employee.pets.add(pet2);
employee.save();
return ok(index.render("added an employee"));
}
public static Result showEmployee(Long id) {
Employee e = Employee.get(id);
//String s = e.address.street;
return ok(employee.render(e));
}
public static Result deleteEmployee(Long id) {
Employee.delete(id);
return ok(index.render("deleted employee " + id));
}
}
Models
Employee.java
#Entity
public class Employee extends Model {
#Id
public Long employee_id;
public String firstName;
public String lastName;
public BigDecimal salary;
#OneToOne(cascade=CascadeType.ALL)
#JoinColumn(name="owner_id")
public Address address;
#OneToMany(cascade=CascadeType.ALL)
#JoinColumn(name="owner_id", referencedColumnName="employee_id")
public List<Pet> pets;
public static Employee get(Long id) {
return find.byId(id);
}
public static void delete(Long id) {
find.byId(id).delete();
}
public static Finder<Long, Employee> find = new Finder<Long,Employee>(Long.class, Employee.class);
}
Address.java
#Entity
public class Address extends Model {
#Id
public Long address_id;
public String street;
public String city;
public String province;
public String country;
public String postalCode;
}
Pet.java
#Entity
public class Pet extends Model {
#Id
public Long pet_id;
public String petString;
}
Views
employee.scala.html
#(employee: models.Employee)
#import helper._
#main("employee view") {
<p>#employee.firstName</p>
<p>#employee.lastName</p>
<p>#employee.salary</p>
<p>#employee.address.country</p>
<p>#employee.pets(1).petString</p>
#for(pet <- employee.pets) {
<p>#pet.petString</p>
}
}
If I render the view above using a URL like localhost:9000/employee/1 I get the following displayed in the browser:
John
Doe
123456
cat
dog
cat
Notice that the address's country is not displayed. I've also tried accessing it in the controller and printing it to the command window, which prints NULL.
However, I found that if I added getters to the Address class, I can retrieve it in the scala template:
Adding
public String getCity() {
return city;
}
...
to Address.java results in
John
Doe
123456
United States of America
cat
dog
cat
So I am able to set an address and assign it to an employee (it shows up in my DB). Also, deleting an employee correctly cascades and deletes the Address in the database. Likewise, this works for the Pet class which is OneToMany. So why do I need to add getters to access my Address properties, but not for Pet? Is my one-to-one relationship not set up correctly in the Java annotations?
EBean does not support lazy loading with direct property access.
Within Java-Controller-Code, the statement employee.address.country is enhanced to something like employee.getAddress().getCountry(). This, alas, is not done in Scala code, specifically not in the templates.
employee.pets(1).petString, on the other hand, is translated to employee.pets.get(1).petString, which is enough for EBean to lazy load, because an EBean LazyList is involved.
Don't stick back to getters/setters please! The Play! people argue you should know in the controller what data you need and fetch it at query time:
public static Employee get(Long id) {
return find.fetch("address").where().idEq(id).findUnique();
}