I am working on a project that has a function that allows users to import a file (Excel or CSV) to DB (MsSQL). I have read tutorials on the internet and followed them, but the problem is one of my entities contains an object.
#NoArgsConstructor
#AllArgsConstructor
#Getter
#Setter
#Entity
#Table(name = "question_bank")
public class QuestionBank implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column
private String content;
#Column
private String explanation;
#Column
private String option1;
#Column
private String option2;
#Column
private String option3;
#Column
private String option4;
#Column
private String answer;
#ManyToOne(fetch = FetchType.LAZY, cascade=CascadeType.ALL)
#JoinColumn(name = "status_id")
private Status status;
#ManyToOne(fetch = FetchType.LAZY, cascade=CascadeType.ALL)
#JoinColumn(name = "levelId")
private QuizLevel quizLevel;
The status_id and levelId are from joining other columns of other tables. And this is the code that I use to set the data from Excel file
questionBank.setAnswer(excelData.get(i));
questionBank.setContent(excelData.get(i + 1));
questionBank.setExplanation(excelData.get(i + 2));
questionBank.setOption1(excelData.get(i + 3));
questionBank.setOption2(excelData.get(i + 4));
questionBank.setOption3(excelData.get(i + 5));
questionBank.setOption4(excelData.get(i + 6));
questionBank.setStatus(Integer.valueOf(excelData.get(i + 8)));
questionBank.setCourse(Integer.valueOf(excelData.get(i + 9)));
questionBank.setQuizLevel(Integer.valueOf(excelData.get(i + 10)));
The IDE said the last 3 lines, setStatus, setCourse and setQuizLevel are errors because there are no functions like that in Entity QuestionBank.
How can I do this import, thank you if you are reading and have a solution for me?
For the last object I guess you will have to construct an instance of QuizLevel, fill it with values then pass it to your setter.
I do not know how your csv is structured, but if you isolate the values related to QuizLevel then pass it to your QuestionBank instance;
QuizLevel quizLevel= new QuizLevel();
quizLevel.setValue(myValueFromCsv)
quizLevel.setOtherValue(myOtherValueFromCSV)
questionBank.setQuizLevel(quizLevel);
Same goes for setCourse and setStatus.
You have to make the instance of your Status and Quizlevel object, and after that, you can access or set the values accordingly of these objects. You can't simplily set the value to a object. First create instance of object then the set or get the values associated with that object.
This example might help you properly:
Post post = new Post();
User user = userServiceImpl.getCurrentUser();
post.setTitle(title);
post.setContent(content);
post.setCreatedAt(time);
post.setAuthor(user.getName());
post.setPublishedAt(time);
post.setUpdatedAt(time);
post.setExcerpt(content);
post.setIsPublished(true);
post.setAuthorId(user.getId());
String[] tagsArray = tags.split(" ");
List<Tag> tagList = new ArrayList<Tag>();
for (String tag : tagsArray) {
Tag tagObject = new Tag();
if (tagService.checkTagWithName(tag)) {
tagList.add(tagService.getTagByName(tag));
} else {
tagObject.setName(tag);
tagObject.setCreatedAt(time);
tagObject.setUpdatedAt(time);
tagList.add(tagObject);
}
}
post.setTags(tagList);
postService.savePost(post);
This is my model class for post with a tag object in last:
#Table(name = "posts")
public class Post {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "title")
private String title;
#Column(name = "excerpt")
private String excerpt;
#Column(name = "content",columnDefinition="TEXT")
private String content;
#Column(name = "author")
private String author;
#Column(name = "published_at")
private Timestamp publishedAt;
#Column(name = "is_published")
private Boolean isPublished;
#Column(name = "created_at")
private Timestamp createdAt;
#Column(name = "updated_at")
private Timestamp updatedAt;
#Column(name = "authorId")
private Long authorId;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "post_tags",
joinColumns = {#JoinColumn(name = "post_id" , referencedColumnName = "id")},
inverseJoinColumns = {#JoinColumn(name = "tag_id", referencedColumnName = "id")})
private List<Tag> tags;
Related
I am trying to get Order[] Array which includes all Orders where the associated document isn't received.
I tried this query and it returns the right number of rows.
#Query("Select o FROM Order o INNER JOIN o.properties p INNER JOIN p.documents d WHERE d.received = false")
Order[] findUnreceivedOrders();
The problem is, the order objects in my array includes ALL documents not only the unreceived, but I want that the object only includes the unreceived document objects.
Does anyone know how to solve this?
Thanks for help!
Order.java
#Entity
#Table(name = "orders")
#JsonIgnoreProperties(ignoreUnknown = true,
value = {"progress"})
public class Order {
#Id
#Column(name = "id", unique = true)
private String orderid;
#Column(name = "user_id")
private String userid;
#Column(name = "entrydate")
private java.sql.Date entrydate;
#Column(name = "info")
private String info;
#Column
private boolean complete;
#Column(name= "cached")
private boolean cached;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "order")
private List<Property> properties = new ArrayList<>();
#OneToOne(mappedBy = "order", cascade = CascadeType.ALL)
private BillingAdress billingAdress;
// Getter & Setter
Property.java
#Entity
#Table(name = "properties")
#JsonIgnoreProperties(ignoreUnknown = true,
value = {"progress"})
public class Property
{
#Id
#Column(name = "propertyid", unique = true )
private String id;
#Column(name = "name")
private String name;
#Column(name = "street")
private String street;
#Column(name = "zip")
private String zip;
#Column(name = "town")
private String town;
#Column
private String house_number;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "property")
private List<Landregisterfolio> landregisterfolios = new ArrayList<>();
#Column(name = "userid" )
private String userid;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "property")
private List<Document> documents = new ArrayList<>();
#ManyToOne
#JoinColumn(name = "order_id")
#JsonIgnore
private Order order;
#Column(name = "order_id", insertable = false, updatable = false)
private String orderid;
//Getter & Setter
}
Document.java
#Entity
#Table(name = "documents")
public class Document {
#Id
#Column(name="id")
private String docid;
#Column(name="name")
private String docname;
#Column(name = "received")
private Boolean received;
#Column(name = "requested")
private Boolean requested;
#Column(name ="last_contact")
private Date lastContact;
#Column(name ="intern_comment")
private String intern_comment;
#Column(name ="extern_comment")
private String extern_comment;
#Column(name="fees")
private double fees;
#ManyToOne
#JoinColumn(name = "property_propertyid")
#JsonIgnore
private Property property;
#Column(name = "property_propertyid", insertable = false, updatable = false)
private String propertyid;
//Getter & Setter
}
Probably you can map #ManyToOne Order to your Document entity and after use for Order entity
#JoinColumnOrFormula(formula = #JoinFormula("(select d.id from documents d WHERE d.order_id = id AND d.received = false"))
List<Document> unreceivedDocuments;
U have list of Property in Order and list of Document in Property. So if u have one Document with status not received in your list u will have this Order.
Thanks to #pdem !
Used "join fetch", changed my lists to sets and it works fine.
I have 2 tables project and employee have multiple relationship. Project has many employees, employee can join many projects( many to many). project have one employee whose is team leader, an employee can manager many projects(many to one). So how do I design database, and classes model mapping with database. Some one help me
This is my code
class user
#Entity(name = "USERS")
public class Users {
#Id
#Column(name = "USER_ID", length = 6)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer userId;
#Column(name = "USER_NAME", length = 50, nullable = false)
private String userName;
#Column(name = "PASS_WORD", length = 50, nullable = false)
private String passWord;
#Column(name = "FULL_NAME", length = 50, nullable = false)
private String fullName;
#Column(name = "EMAIL", length = 50, nullable = false)
private String email;
#Column(name = "PHONE", length = 11, nullable = true)
private String phone;
#Column(name = "STATUS", nullable = true)
private Boolean status;
#ManyToMany(fetch = FetchType.LAZY)
#JsonIgnore
#JoinTable(name = "USERPROJECT", joinColumns = { #JoinColumn(name =
"USER_ID") }, inverseJoinColumns = {
#JoinColumn(name = "PROJECT_ID") })
private List<Project> projects;
#OneToMany(mappedBy = "teamlead")
private List<Project> projectOfTeamLead;
//get set.....
}
class project
#Entity(name = "PROJECTS")
public class Project {
#Id
#Column(name = "PROJECT_ID", length = 6)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer projectId;
#Column(name = "PROJECT_NAME", length = 50, nullable=false)
private String projectName;
#Column(name = "USER_CREATE_ID", length = 6, nullable=false)
private Integer userCreateId;
// #Column(name = "TEAM_LEAD_ID", length = 6, nullable=false)
// private Integer teamLeadId;
#Column(name = "TIME_START", nullable=true)
private Date timeStart;
#Column(name = "TIME_END", nullable=true)
private Date timeEnd;
#ManyToMany(mappedBy = "projects")
private List<Users> users;
#ManyToOne
#JoinColumn(name = "TEAM_LEAD_ID")
private Users teamlead;
//get set...
}
I think you need to make your database fit into 3nf (third normal form). You are describing a database that uses two tables, but I think you need three at least, that way you can describe what employees are on what project. A "team" table that uses the PK's from the other two tables should be used. Conventionally, you would name it something like "ProjectEmployees" as it is comprised of the PK's from the "Projects" table and the "Employees" table respectively. I hope that answers your question. If you don't understand what I'm talking about, I highly recommend you watch this.
I had entity for JSON parsing
#Entity
public class Product{
private int productId;
private String productName;
private BigDecimal productPrice;
private int productVendorId;
private String productVendorName;
private int productCategoryId;
private String productCategoryName;
//getters setters here
created 3 tables in dataBase:
products (product_id, product_name,product_price, product_vendor_id), product_category_id);
vendors(vendor_id, vendor_name); categories (category_id, category_name);
in 1st table product_vendor_id fk -> vendor_id pk in vendors and product_category_id fk -> category_id pk in categories
i tried something like this:
#Entity
#Table(name = "products, schema = "market")
public class Product
#Id
#Column(updatable = false, nullable = false, name = "product_id")
private int Id;
#Column(name = "product_name")
private String productName;
#Column(name = "product_price")
private BigDecimal productPrice;
#Column(name = "product_vendor_id")
private int productVendorId;
#Columnt(table = "vendors", name = "vendor_name")
private String vendor_name;
#Column(name = "product_category_id")
private int productCategoryId;
#Column(table = "categories", name = "category_name")
private String productCategorName;
//getters setters here
received alot of errors: like i have not category_name column in products table etc. this error i received when used
#Table(name = "products", schema = "market" )
#SecondaryTables({#SecondaryTable(name = "vendors", schema = "market"),
#SecondaryTable(name = "categories", schema = "market")})
#JsonIgnoreProperties(ignoreUnknown = true)
public class Product {
....
#JoinColumn(name = "product_vendor_id", referencedColumnName = "vendor_id")
private int productVendorID;
#JoinColumn(table = "vendors", name = "vendor_name")
private String productVendorName;
#JoinColumn(name = "product_category_id", referencedColumnName =
"product_category_id")
private int productCategoryID;
#JoinColumn(table = "categories", name = "category_name")
private String productCategoryName;
exception:
Caused by: org.postgresql.util.PSQLException: ERROR: column
product0_1_.product_id doesn't exist
Hint: There may have been a link to the "product0_.product_id" column
Position: 705
how can i map this entity on 3 tables?
upd: i don't want separate this entity, i need this for deserialize my json object too, just want reuse this entity on different operations.
example of json
{"productID":"1111111","productName":"Cool product","productPrice":"99.99","productVendorName":"Some store","productVendorID":"1337","productCategoryName":"Food","productCategoryID":"1"}
Since there are 3 separate tables, you would want to create three separate entity classes.
Also I'm assuming vendors and category tables will have one to many relation to product.
Try below code:
Product:
#Entity
public class Product {
#Id
private int productId;
private String productName;
private BigDecimal productPrice;
private String productVendorName;
private String productCategoryName;
#ManyToOne
#JoinColumn(name = "productCategoryId")
private Category category;
#ManyToOne
#JoinColumn(name = "productVendorId")
private Vendors vendor;
}
Category:
#Entity
public class Category {
#Id
private Integer categoryId;
private String categoryName;
#OneToMany(mappedBy = "category", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
#NotEmpty
private List<Product> products = new ArrayList<>();
}
Vendors:
#Entity
public class Vendors {
#Id
private int vendorId;
private String vendorName;
#OneToMany(mappedBy = "vendor", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
#NotEmpty
private List<Product> products = new ArrayList<>();
}
Though, I would recommend using above approach, if you still want to have single entity class and 3 separate table with redudant data then use below:
#Entity
#SecondaryTables({ #SecondaryTable(name = "vendors"), #SecondaryTable(name = "categories") })
public class Product {
#Id
private int productId;
private String productName;
private BigDecimal productPrice;
private String productVendorName;
private String productCategoryName;
#Column(table = "categories")
private Integer categoryId;
#Column(table = "categories")
private String categoryName;
#Column(table = "vendors")
private int vendorId;
#Column(table = "vendors")
private String vendorName;
}
The id column of the main table will be present in all the 3 tables and used for joining them.
Sorry for poor wording of the question, just didn't know how to explane what i wanted.
All what i need just add #transient annotations for fields which i don't have in products table, and separate it like accepted answer was suggested.
#Entity
#Table(name = "products", schema = "store" )
#JsonIgnoreProperties(ignoreUnknown = true)
public class Product {
#Id
#Column(updatable = false, nullable = false, name = "product_id")
private int productId;
#Column(name = "product_name")
private String productName;
#Column(name = "product_price")
private BigDecimal productPrice;
#Transient
private String productVendorName;
#Transient
private String productCategoryName;
#Transient
private int vendorId;
#Transient
private int categoryId;
#ManyToOne
#JoinColumn(name = "product_category_id")
private Category category;
#ManyToOne
#JoinColumn(name = "product_vendor_id")
private Vendor vendor;
}
for vendors table entity
#Entity
#Table(name = "vendors", schema = "store")
public class Vendor {
#Id
#Column(name = "vendor_id")
private int vendorId;
#Column(name = "vendor_name")
private String vendorName;
#OneToMany(mappedBy = "vendor", cascade = CascadeType.ALL, fetch = FetchType.LAZY,
orphanRemoval = true)
#NotNull
private List<Product> products = new ArrayList<>();
}
and for categories
#Entity
#Table(name = "categories", schema = "store")
public class Category {
#Id
#Column(name = "category_id")
private Integer categoryId;
#Column(name = "category_name")
private String categoryName;
#OneToMany(mappedBy = "category", cascade = CascadeType.ALL, fetch = FetchType.LAZY,
orphanRemoval = true)
#NotNull
private List<Product> products = new ArrayList<>();
}
Wanted to leave here full answer on my question, maybe someone will need it later
Just check some problems with toString. Use it only in Product.class and better make 2 versions for print json and jpa.
I created my app using JHipster. When i try to get list of tournaments via TournamentQueryService i get this error :
Exception in TournamentQueryService.findByCriteria() with cause =
'org.hibernate.HibernateException: Unable to access lob stream' and
exception = 'Unable to access lob stream; nested exception is
org.hibernate.HibernateException: Unable to access lob stream'
This is filter and Page object :
find by criteria : TournamentCriteria{}, page: Page request [number:
0, size 8, sort: startDate: DESC]
So it just gets 8 first tournaments.
This is tournament class :
#Entity
#Table(name = "tournament")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#Document(indexName = "tournament")
public class Tournament extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#Column(name = "name")
private String name;
#Column(name = "location")
private String location;
#Column(name = "url")
private String url;
#Column(name = "start_date")
private ZonedDateTime startDate;
#Column(name = "end_date")
private ZonedDateTime endDate;
#Column(name = "entry_fee")
private Double entryFee;
#Column(name = "prize")
private Double prize;
#Column(name = "goods")
private String goods;
#Column(name = "favorite_rating")
private Long favoriteRating;
#Column(name = "participants_number")
private Integer participantsNumber;
#Column(name = "finished")
private Boolean finished;
#Column(name = "view_only")
private Boolean viewOnly;
#Column(name = "image")
private String image;
#Column(name = "description")
private String description;
#Column(name = "teams_applied")
private String teamsApplied;
#Lob
#Column(name = "schedule")
private String schedule;
#Lob
#Column(name = "prize_distribution")
private String prizeDistribution;
#Lob
#Column(name = "contacts")
private String contacts;
#Lob
#Column(name = "rules")
private String rules;
#OneToMany(mappedBy = "tournament", fetch = FetchType.LAZY)
#JsonIgnore
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Stream> streams = new HashSet<>();
#ManyToMany(fetch = FetchType.EAGER)
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#JoinTable(name = "tournament_platforms", joinColumns = #JoinColumn(name = "tournaments_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "platforms_id", referencedColumnName = "id"))
private Set<Platform> platforms = new HashSet<>();
#ManyToOne
private Game game;
#ManyToOne
private TournamentStatus status;
#ManyToOne(fetch = FetchType.LAZY)
private EntryType entryType;
#ManyToOne(fetch = FetchType.LAZY)
private TournamentFormat format;
#ManyToOne
private Region region;
#ManyToOne(fetch = FetchType.LAZY)
private GameMode gameMode;
#ManyToOne(fetch = FetchType.LAZY)
private PrizeType prizeType;
#ManyToOne
private Organizer organizer;
#ManyToOne(fetch = FetchType.LAZY)
private TournamentStage stage;
#ManyToOne
private HostPlatform hostPlatforms;
#ManyToOne(fetch = FetchType.LAZY)
private TournamentType type;
#ManyToOne
private PlayType playType;
#ManyToOne
private Currency currency;
#ManyToOne
private Country country;
Here is the method that calls hibernate :
#Transactional(readOnly = true)
public Page<Tournament> findByCriteria(TournamentCriteria criteria, Pageable page) {
log.info("find by criteria : {}, page: {}", criteria, page);
final Specifications<Tournament> specification = createSpecification(criteria);
Page<Tournament> result = tournamentRepository.findAll(specification, page);
return result;
}
Is it possibile that you are trying to access Lob properties when hiberante session is closed?
Try to replace your #Lob properties with the following:
#Basic(fetch=FetchType.EAGER) #Lob
and check if the error persists.
I'm trying to achieve something like sql command below by using HQL and JPA.
Instead of "SELECT user_id..." I need SELECT OBJECT(o).
SELECT user_id FROM posix_user o INNER JOIN postgre_user n ON n.id=o.user_id WHERE n.name='USERNAME2'
I have some problems with this part of the code in JPA DAO:
public List<PosixUserEntity> listPosixUsers(final String uid_number) {
final StringBuilder queryString = new StringBuilder("SELECT OBJECT(o) FROM ");
queryString.append(this.entityClass.getSimpleName());
queryString.append(" o JOIN com.services.dao.user.jpa.UserEntity n ON (n.id=o.user_id) WHERE n.name LIKE :uid_number");
final Query findByNameQuery = entityManager.createQuery(queryString.toString()).setParameter("uid_number", uid_number);
return findByNameQuery.getResultList();
}
JOIN ON is not allowet here and I did not know how to replace it.
Also how can I replace com.services.dao.user.jpa.UserEntity by something cleaner.
There is my Entites, they may need to be improved:
#Entity
#Table(name = "posix_user")
public class PosixUserEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
//#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
private String user_id;
#Column(name = "uid_number")
private String uid_number;
#Column(name = "home_directory")
private String home_directory;
#Column(name = "login_shell")
private String login_shell;
#Column(name = "group_id")
private String group_id;
//getters,setters....
#Entity
#Table(name = "postgre_user")
#SQLDelete(sql = "update postgre_user set status = 'removed' where id = ?")
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name", unique = true, nullable = false)
private String name;
#Column(name = "password")
private String password;
#Enumerated(EnumType.STRING)
#Column(name = "status")
private UserStatus status;
#Column(name = "firstname")
private String firstName;
#Column(name = "lastname")
private String lastName;
#Column(name = "email")
private String email;
#Column(name = "usertype")
private String userType;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
private List<UserRoleTargetGroupEntity> userRoleTargetGroupEntity;
#Column(name = "last_login")
private String lastLogin;
#Column(name = "previous_login")
private String previousLogin;
#JsonIgnore
#Column(name = "change_password_flag")
private Boolean userPasswordResetFlag;
#OneToOne(cascade=CascadeType.ALL)
#PrimaryKeyJoinColumn
private PosixUserEntity posixUserEntity;
You may also need to know that FOREIGN KEY (user_id) REFERENCES postgre_user (id) - it should look like that
Can you know how can I modify my SELECT?
I've tested a simplified version of your classes
#Entity
#Table(name = "posix_user")
public class PosixUserEntity {
#Id
#Column(name = "user_id")
private Long user_id;
// getter + setter
}
#Entity
#Table(name = "postgre_user")
public class UserEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#OneToOne(cascade=CascadeType.ALL)
#PrimaryKeyJoinColumn
private PosixUser posixUserEntity;
// getter + setter
}
And this JPQL query works as expected
String jpql = "SELECT p "
+ "FROM UserEntity n JOIN n.posixUserEntity p "
+ "WHERE n.name LIKE :uid_number)";
JOIN is allowed because you have mapped the relationship in UserEntity.
and you don't need to specify the complete name of your entity class.
Check if it has been included when you define your persistence unit.
Hope this helps.