I have three tables : po_dtl and workbook_types.
Each purchase order line (po_dtl) will have "workbook_code" column to refer to workbook_types.
Basically, po_dtl.workbook_code is only a lookup code to workbook_types.workbook_code.
The simplified java class are
#Entity
#Table(name="po_dtl")
public class PurchaseOrderDtl {
#Id
#Column(name = "po_dtl_id")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "po_dtl_s")
#SequenceGenerator(name = "po_dtl_s", sequenceName = "po_dtl_s", allocationSize = 1, initialValue = 1)
private long id;
#Column(name = "price_base", length = 7)
private int priceBase;
// ??? What is the annotation for workbook_Types?
private WorkbookType workbookType;
....
}
While the workbook_types
#Entity
#Table(name = "workbook_types")
public class WorkbookType {
#Id
#Column(name = "workbook_code")
private String workbookCode;
#Column(name = "description", length = 255)
private String description;
#Column(name = "file_root_path", length = 255)
private String fileRootPath;
....
}
What i ussualy use (without hibernate) is :
workbook_types.workbook_code contains string "wbook_finance",
"wbook_marketing"
each po_dtl.workbook_code will contains "wbook_finance" or
"wbook_marketing"
workbook_types will only contains 2 rows with unique workbook_code, while po_dtl will contains many rows, but each row must contains only "wbook_finance" or "wbook_marketing"
Thanks
As i understand your question, you need #ManyToOne
Or use enum if new workbook_type's added only at developing stage.
#Entity
class Country { //Country Dictionary
}
#Entity
class User {
#ManyToOne
private Country country;
}
see How to design tables for data dictionary when using hibernate?
Related
I'm learning how Spring framework works and as an example I'm trying to save cities and countries which users can log using the API endpoints. However, I can't figure out how to prevent duplicate entries.
For example I'm adding 2 cities in a country using the endpoint (photo below) but in the Country table I get duplicate values. How can I prevent duplicate values ? Thanks in advance.
#Getter
#Setter
#Entity
#Table(name = "COUNTRY")
public class CntCountry {
#Id
#SequenceGenerator(name = "CntCountry", sequenceName = "CNT_COUNTRY_ID_SEQ")
#GeneratedValue(generator = "CntCountry")
private Long id;
#Column(name = "COUNTRY_NAME", length = 30, nullable = false)
private String countryName;
#Column(name = "COUNTRY_CODE", length = 30, nullable = false)
private String countryCode;
}
#Getter
#Setter
#Table(name = "CITY")
#Entity
public class CtyCity {
#Id
#SequenceGenerator(name = "CtyCity", sequenceName = "CTY_CITY_ID_SEQ")
#GeneratedValue(generator = "CtyCity")
private Long id;
#Column(name = "CITY_NAME", length = 30, nullable = false)
private String cityName;
#Column(name = "PLATE_NUMBER", length = 30, nullable = false)
private Long plateNumber;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "FK_COUNTRY")
private CntCountry country;
}
EDIT:
#PostMapping("/city")
public ResponseEntity<CtyCityDto> save(#RequestBody CtyCitySaveRequestDto ctyCitySaveRequestDto){
CtyCityDto ctyCityDto = ctyCityService.save(ctyCitySaveRequestDto);
return ResponseEntity.ok(ctyCityDto);
}
#Service
#AllArgsConstructor
public class CtyCityService {
private CtyCityDao ctyCityDao;
public CtyCityDto save(CtyCitySaveRequestDto ctyCitySaveRequestDto){
CtyCity ctyCity = CtyCityMapper.INSTANCE.convertToCtyCity(ctyCitySaveRequestDto);
ctyCity = ctyCityDao.save(ctyCity);
CtyCityDto ctyCityDto = CtyCityMapper.INSTANCE.convertToCtyCityDto(ctyCity);
return ctyCityDto;
}
}
public interface CtyCityDao extends JpaRepository<CtyCity,Long> {
}
#Data
public class CtyCityDto {
private Long id;
private String cityName;
private Long plateNumber;
private CntCountry country;
}
I'm not really following your naming conventions, and I think your DTO classes are just complicating things for you at this point... But in general terms, because the entities you're sending have no id value associated with them, JPA assumes they are different objects and adds them to the database with new id's because it hasn't been told anywhere that similar items might in fact be the same object, it needs to be told.
I can think of 2 ways to prevent entity duplication in your database.
1. The easiest way would be to set your Country and City names (or other attributes) to be "unique", you can do this in your entity classes simply by adding unique = true to the column data on the item you wish to be unique.
//In Country.java
#Column(name = "COUNTRY_NAME", length = 30, nullable = false, unique = true)
private String countryName;
//In City.java
#Column(name = "CITY_NAME", length = 30, nullable = false, unique = true)
private String cityName;
Although, you will then need to handle exceptions thrown if a duplicate is provided, in Spring Boot the best way to handle this is with a #ControllerAdvice but that's another subject.
2. Check if the entity exists by name or some other value. A common approach might be something like the following:
//In your service
public Object saveCountry(Country country){
Country existingCountry = countryRepository.findByName(country.getName()).orElse(null);
if(existingCountry == null){
//Country does not already exist so save the new Country
return countryRepository.save(country);
}
//The Country was found by name, so don't add a duplicate
else return "A Country with that name already exists";
}
//In your Country repository
Optional<Country> findByName(countryName);
In case my answer doesn't make sense, I have thrown together an example following my first suggestion (using the unique column attribute and a controller advice) which you can view/clone from here
I'm stuck with a problem in Java, hibernate (jpa)
So, I have 2 classes: Class and Classroom, each one being entities
#Entity
#Table(name = "CLASSES")
public class Class {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="ID")
private Long id;
#Column(name = "TEACHER_ID")
private Long teacherId;
#Column(name = "NAME")
private String name;
#Column(name = "YEAR")
private Integer year;
#Column(name = "SECTION")
private String section;
}
#Entity
#Table(name = "CLASSROOMS")
public class Classroom {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Long id;
#Column(name = "NAME")
private String name;
#Column(name = "LOCATION")
private String location;
#Column(name = "CAPACITY")
private Integer capacity;
}
Also, I have another java class called Planner which connect these two classes (their tables - using classroom_id and class_id); I have a table for this Planner
#Entity
#Table(name = "PLANNERS")
public class Planner {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Long id;
#Column(name = "CLASSROOM_ID")
private Long classroomId;
#Column(name = "CLASS_ID")
private Long classId;
#Column(name = "STARTTIME")
private Time startTime;
#Column(name = "ENDTIME")
private Time endTime;
#Column(name = "DATA")
private Date date;
}
What I need: a new entity (or just output data) which will include all fields from PLANNERS, field NAME from CLASSES and field NAME from CLASSROOMS.
In SQL, this query is:
select M.classroom_id, M.class_id, M.starttime, M.endtime, M.data, CL.NAME AS "ROOM NAME (FROM CLASSROOMS)", C.NAME AS "COURSE NAME (FROM CLASSES)" FROM PLANNERS M INNER JOIN CLASSROOMS CL ON CL.ID = M.CLASSROOM_ID INNER JOIN CLASSES C ON C.ID = M.CLASS_ID
(inner join using classroom_id and class_id)
How can I do this on hibernate jpa? I want to get the objects (rows) returned by the above query.
I searched a lot, I find about join column, other annotations (e.g. OneToMany etc) but I didn't succeed, so I need help
I'm using the following code to collect data from two different tables, but it's giving me records from the meal table even if there are not any records in the allergies table but I want to do a INNER JOIN from both tables instead. I don't want to get any records from the meal table if I don't have any records in the allergies table that match the same id inside the meals table.
Please advise I have been stock with this for days.
#Entity
#Table(name = "meal")
#SecondaryTable(name = "allergens", pkJoinColumns = #PrimaryKeyJoinColumn(name = "meal_id"))
class Meal {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
Long id;
#Column(name = "name")
String name;
#Column(name = "description")
String description;
#Column(name = "price")
BigDecimal price;
#Column(name = "peanuts", table = "allergens")
boolean peanuts;
#Column(name = "celery", table = "allergens")
boolean celery;
#Column(name = "sesame_seeds", table = "allergens")
boolean sesameSeeds;
// standard getters and setters
}
I found this solution that is working using: "#org.hibernate.annotations.Table(appliesTo = "allergens", optional = false)":
Example:
#Entity
#Table(name = "meal")
#org.hibernate.annotations.Table(appliesTo = "allergens", optional = false)
#SecondaryTable(name = "allergens", pkJoinColumns = #PrimaryKeyJoinColumn(name ="meal_id"))
class Meal {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
Long id;
#Column(name = "name")
String name;
#Column(name = "description")
String description;
#Column(name = "price")
BigDecimal price;
#Column(name = "peanuts", table = "allergens")
boolean peanuts;
#Column(name = "celery", table = "allergens")
boolean celery;
#Column(name = "sesame_seeds", table = "allergens")
boolean sesameSeeds;
// standard getters and setters
}
If the identity is driven by the allergens table then you should map the entity to that table and use the meals table instead as secondary table.
#Entity
#Inheritance(JOINED)
public abstract class Allergens {
}
#Entity
public class Meals extends Allergens {
}
I am new to Spring and JPA and I am trying to write a job in Spring which runs every 3 hours and retrieve the records from Oracle Database.
I would like to only read the new/updated content from the past 3 hours (ideally from the last job run).
I have seen few examples in https://spring.io/blog/2011/02/10/getting-started-with-spring-data-jpa/ where we can create queries and retrieve the data based on our requirements, but in my current use case, I am not using queries instead using the java classes with the annotations and using Join columns between different tables. There are chances that only one of the sub table is updated or all the tables are updated with new content. I need to get the results if at least one of the table is updated/inserted with new content.
Campus is the main table and retrieves the data from Group and Region, I need to fetch the data if any new data is updated in Campus table or even any group/region is added/modified.
I am using JDK7 as of now.
Is there a way to accomplish the above requirement?
Below are the sample Java classes for reference.
#Entity
#EntityListeners(AuditListener.class)
#Table(name = "TABLE_CAMPUS")
public class Campus implements Auditable {
#Id
#Column(name = "ID)
#SequenceGenerator(name = "SIMPLE_ID", sequenceName = "SIMPLE_ID")
#GeneratedValue(generator = "SIMPLE_ID", strategy = GenerationType.AUTO)
private Long id;
#Column(name = "CAMPUS_NAME")
private String campusName;
#Column(name = "CAMPUS_ID", nullable = false)
private Long campusId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "GROUP_ID")
private GroupType groupType;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "REGION_ID")
private Region region;
....
...
}
#Entity
#EntityListeners(AuditListener.class)
#Table(name = "TABLE_GROUP_TYPE")
public class GroupType implements Auditable {
#Id
#Column(name = "GROUP_TYPE_ID")
#SequenceGenerator(name = "GROUP_TYPE_SEQUENCE", sequenceName = "GROUP_TYPE_ID")
#GeneratedValue(generator = "GROUP_TYPE_SEQUENCE", strategy = GenerationType.AUTO)
protected Long id;
#Column(name = "GROUP_TYPE_NAME", nullable = false)
protected String groupTypeName;
....
...
}
#Entity
#EntityListeners(AuditListener.class)
#Table(name = "TABLE_REGION")
public class Region implements Auditable {
#Id
#Column(name = "region_id")
#SequenceGenerator(name = "REGION_ID", sequenceName = "REGION_ID")
#GeneratedValue(generator = "REGION_ID", strategy = GenerationType.AUTO)
private Long id;
#Column(name = "REGION_NAME", nullable = false)
private String name;
...
..
}
Any help is Appreciated.
I've two entity with #OneToMany relationship
First Entity
#Entity
#Table(name = SchemaConstant.RESCHEDULE_TABLE_NAME)
public class RescheduleRequestEntity extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "RESCHEDULE_ID_GEN")
#SequenceGenerator(
name = "RESCHEDULE_ID_GEN",
allocationSize = 1,
sequenceName = SchemaConstant.RESCHEDULE_SEQUENCE_NAME)
private Long id;
private String adviseNo;
private LocalDate adviseDate;
private Long customerId;
#Enumerated(value = EnumType.STRING)
private AdviceStatus status;
#OneToMany(mappedBy = "reschedule", fetch = FetchType.LAZY)
private List<RescheduleDetailEntity> accountDetails;
}
Second Entity
#Entity
#Table(name = "RESCHEDULE_DETAILS")
public class RescheduleDetailEntity extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "RESCHEDULE_DETAILS_ID_GEN")
#SequenceGenerator(
name = "RESCHEDULE_DETAILS_ID_GEN",
allocationSize = 1,
sequenceName = "S_RESCHEDULE_DETAILS")
private Long id;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ACCOUNT_ID", nullable = false)
private AccountEntity account;
#Enumerated(value = EnumType.STRING)
private AdviceStatus status;
#Enumerated(value = EnumType.STRING)
private TenureType tenureType;
private Integer tenure;
#ManyToOne
#JoinColumn(name = "ADVISE_ID")
private RescheduleDetailEntity reschedule;
}
AND Enum
public enum AdviceStatus {
OPEN,
ACTIVE,
CLOSE
}
I want to fetch data with condition Like
SELECT *
FROM RESCHEDULEREQUESTENTITY R, RESCHEDULEDETAILENTITY D
WHERE R.ID = :PID
AND D.ADVISEID = R.ID
AND D.STATUS <> "CLOSE"
"Data fetch from RescheduleRequestEntity with data from RescheduleDetailEntity where RescheduleDetailEntity.status is not equal "CLOSE" where "Status" is Enum type".
I create a JPA Repository class like following for fetch data
#Repository
public interface RescheduleRequestRepository
extends JpaRepository<RescheduleRequestEntity, Long>, JpaSpecificationExecutor {
Optional<RescheduleRequestEntity> findByAdviseNo(String adviceNo);
Optional<RescheduleDetailEntity> findByIdAndAccountDetails_StatusNot(
Long adviceId, AdviceStatus status);
}
but it's not fetch data with my desired condition,it's not ignore data which have Status "CLOSE"
You can make it a custom query using #Query annotation.