I have an Bid entity defined as follows
#ToString
#NoArgsConstructor
#AllArgsConstructor
#Setter
#Getter
#Entity
#Table(name = "bid_details")
public class Bid {
private enum STATUS { INITIATED, DRAFT, COMPLETED }
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false, updatable = false)
private Integer id;
#Column(name = "govt_bid_id", nullable = false)
private String govtBidNumber;
#Temporal(TemporalType.DATE)
#Column(name = "release_date", nullable = false)
#JsonFormat(pattern = "dd-MM-yyyy")
private Date releaseDate;
#ManyToOne(optional = false)
#JoinColumn(name = "created_by", referencedColumnName = "id", updatable = false, nullable = false)
private User createdBy;
#Temporal(TemporalType.DATE)
#Column(name = "created_date", nullable = false)
#CreationTimestamp
private Date createdDate;
#ManyToOne
#JoinColumn(name = "updated_by", referencedColumnName = "id", updatable = false, nullable = false)
private User updatedBy;
#Enumerated(EnumType.STRING)
#Column(name = "status", nullable = false)
private STATUS status;
#Column(name = "avg_turnover")
private String avgTurnover;
#Convert(converter = StringListConverter.class)
#Column(name = "docs_required", columnDefinition = "json")
private List<String> docsRequired;
#Enumerated(EnumType.STRING)
#Column(name = "status", nullable = false)
private STATUS status;
}
and the corresponding columns are present in the bid_details tables. I have bid repository defined as follows:
public interface BidRepository extends JpaRepository<Bid, Integer> {
}
now when I try to access data by id using findById it is throwing No Value Present exception whereas if I try to access the data using findAllById I am getting correct result. Not able to figure out what's causing this weird behaviour.
Also, if I execute findAll first and then findById it is giving the correct result.
I am using spring-boot version 2.1.1
following is code where the entity is saved in the db
public Bid addBid(BidRequest bidRequest) {
User user = userRepository.findById(bidRequest.getCreatedBy()).get();
Bid bid = new Bid();
modelMapper.map(bidRequest, bid);
bid.setCreatedBy(user);
return bidRepository.save(bid);
}
BidRequest class is as follows:
#ToString
#NoArgsConstructor
#AllArgsConstructor
#Setter
#Getter
public class BidRequest {
private String govtBidNumber;
#Temporal(TemporalType.DATE)
#JsonFormat(pattern = "yyyy-MM-dd")
private Date releaseDate;
#Temporal(TemporalType.DATE)
private Date endDate;
private int createdBy;
#Temporal(TemporalType.DATE)
#JsonFormat(pattern = "yyyy-MM-dd")
private Date createdDate;
private int updatedBy;
private String status;
private List<String> docsRequired;
}
Have you tried orElse like this
findById(id).orElse(null);
Because findById returns an Optional object so you have to write orElse() after findById()
Related
I need to add 2 extra columns into #ManyToMany table.
My Station Entity
#Entity(name = "stations")
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Station {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false, name = "title")
private String title;
#Column(nullable = false)
private Long entityId;
#ManyToMany
private List<PlaceOfWork> placesOfWork = new ArrayList<>();
#Column(nullable = false, name = "created_date")
private LocalDateTime createdDateTime;
#Column(nullable = false, name = "updated_date")
private LocalDateTime updatedDateTime;
#PrePersist
private void onCreate() {
this.createdDateTime = LocalDateTime.now();
this.updatedDateTime = LocalDateTime.now();
}
#PreUpdate
protected void onUpdate() {
this.updatedDateTime = LocalDateTime.now();
}
}
My PlaceOfWork Entity
#Entity
#Table(name = "places_of_work")
#Data
public class PlaceOfWork {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "entity_id", nullable = false, unique = true)
private Long entityId;
#ManyToOne
#JoinColumn(name = "module_id", nullable = false)
private Module module;
#Column(name = "title", nullable = false)
private String title;
#Column(name = "description", columnDefinition = "text")
private String description;
#Column(name = "created_date", nullable = false)
private LocalDateTime createdDate;
#Column(name = "expired_date")
private LocalDateTime expiredDate;
#Column( name = "updated_date", nullable = false)
private LocalDateTime updatedDate;
#PrePersist
private void onCreate() {
this.createdDate = LocalDateTime.now();
this.updatedDate = LocalDateTime.now();
}
#PreUpdate
protected void onUpdate() {
this.createdDate = LocalDateTime.now();
}
}
After project initialization ORM creates stations_places_of_work table with 2 fields:
station_id
place_of_work_id
I aslo tried to add extra columns by implementing #ManyToMany relation by hand
#Entity
#AllArgsConstructor
#NoArgsConstructor
#Data
public class StationsPlacesOfWork {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "station_id")
private Station station;
#ManyToOne
#JoinColumn(name = "place_of_work_id")
private PlaceOfWork placeOfWork;
#Column(name = "created_date", nullable = false)
private LocalDateTime createdDate;
#Column(name = "expired_date")
private LocalDateTime expiredDate;
private void onCreate() {
this.createdDate = LocalDateTime.now();
}
}
But i recieved next error:Export identifier [stations_places_of_work] encountered more than once
I need to add createdDateTime and expiredDateTime to the table, any suggestions?
I am currently trying my hand at Java Spring Boot and would just like to provide some data via API.
Unfortunately, I have not gotten any further for hours if I made a mistake.
Error message:
org.hibernate.MappingException: Repeated column in mapping for entity: com.acm500.db.CocktailIngredient column: cocktail_id (should be mapped with insert="false" update="false")
Database structure:
CocktailIngredient Entity:
#Table(name = "cocktail_ingredients")
#Entity
public class CocktailIngredient {
#EmbeddedId
private CocktailIngredientId id;
#Column(name = "amount", nullable = false)
private String amount;
#Column(name = "amount_ml")
private String amountMl;
#Column(name = "created_at")
private Instant createdAt;
#Column(name = "updated_at")
private Instant updatedAt;
}
CocktailIngredientId:
#Embeddable
public class CocktailIngredientId implements Serializable {
private static final long serialVersionUID = -6965389309722862577L;
#Column(name = "cocktail_id", nullable = false, updatable = false, insertable = false)
private Long cocktailId;
#Column(name = "ingredients_id", nullable = false)
private Long ingredientsId;
#Column(name = "strength_id", nullable = false)
private Long strengthId;
#Column(name = "orderNo", nullable = false)
private Integer orderNo;
}
I would appreciate any help. Maybe someone has already made this mistake.
Is it possible to create one column for bi-directional relationship?
My Entities:
#Entity
#Table(name = "subscription")
#Proxy(lazy = false)
public class Subscription {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "subscription_id")
private long id;
#Column(name = "userid", nullable = false)
private String userId;
#Column(name = "saledate", nullable = false)
#Temporal(TemporalType.DATE)
private Date saleDate;
#Column(name = "finishdate", nullable = false)
#Temporal(TemporalType.DATE)
private Date finishDate;
#Column(name = "price", nullable = false)
private long price;
#Column(name = "description", nullable = false)
private String description;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "subscription")
private List<VisitDate> visitDates = new ArrayList<>();
}
#Entity
#Table(name="visitdate")
public class VisitDate {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "id")
private long id;
private long subscription;
#Column(name = "date", nullable = false)
#Temporal(TemporalType.DATE)
private Date date;
#ManyToOne
#JoinColumn(name="subscription_id")
private Subscription associatedSub;
}
Now I see two columns in the database and little bit confused.
I don't want to save the same data but want to display a report about how many users visit on some day.
Update:
You are not required to create a separate field "subscription" in VisitDate class. Hibernate will automatically create a field to store subscription id. The code needs to be slightly changed.
#Entity
#Table(name = "subscription")
public class Subscription {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name = "subscription_id")
private long id;
#Column(name = "userid", nullable = false)
private String userId;
#Column(name = "saledate", nullable = false)
#Temporal(TemporalType.DATE)
private Date saleDate;
#Column(name = "finishdate", nullable = false)
#Temporal(TemporalType.DATE)
private Date finishDate;
#Column(name = "price", nullable = false)
private long price;
#Column(name = "description", nullable = false)
private String description;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "associatedSub")
private List<VisitDate> visitDates = new ArrayList<>();
}
Notice, that I have changed the mappedBy property to point at associatedSub in the above class.
#Entity
#Table(name="visitdate")
public class VisitDate {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name = "id")
private long id;
#Column(name = "date", nullable = false)
#Temporal(TemporalType.DATE)
private Date date;
#ManyToOne
#JoinColumn(name="subscription_id")
private Subscription associatedSub;
}
You can use Uni-Directional relationship for the same purpose. You just need to add a list/set of Visits for a particular subscription, You don't have to create a list of subscription for a particular visit.
for reference Visit [Java JPA] :(https://en.wikibooks.org/wiki/Java_Persistence/OneToMany#Undirectional_OneToMany.2C_No_Inverse_ManyToOne.2C_No_Join_Table_.28JPA_2.0_ONLY.29)!
#Entity
#Table(name = "subscription")
#Proxy(lazy = false)
public class Subscription {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "subscription_id")
private long id;
#Column(name = "userid", nullable = false)
private String userId;
#Column(name = "saledate", nullable = false)
#Temporal(TemporalType.DATE)
private Date saleDate;
#Column(name = "finishdate", nullable = false)
#Temporal(TemporalType.DATE)
private Date finishDate;
#Column(name = "price", nullable = false)
private long price;
#Column(name = "description", nullable = false)
private String description;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "subscription")
private List<VisitDate> visitDates = new ArrayList<>();
}
#Entity
#Table(name="visitdate")
public class VisitDate {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "id")
private long id;
private long subscription;
#Column(name = "date", nullable = false)
#Temporal(TemporalType.DATE)
private Date date;
}
I'm using JPA with QueryDSL, In that scenario, I'm going to use JpaQuery Projections for fetching the only required data from DB. In my entity there is one OneToMany(List) Mapping But I'm not able to do projection on OneToMany mapping fields ie List. Please, anyone, tell me how we can get List by using projections in OneToMany mapping.
My entity class:-
public class Brand {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = COLUMN_BRAND_ID)
private int brandId;
#Column(name = COLUMN_BRAND_NAME, columnDefinition = "VARCHAR(255)", nullable = false, unique = true)
private String brandName;
#OneToOne(cascade = CascadeType.MERGE )
#JoinColumn(name = BRAND_LOGO_SMALL_FOREIGN_KEY)
private File brandLogoSmall;
#OneToOne(cascade = CascadeType.MERGE)
#JoinColumn(name = BRAND_LOGO_LARGE_FOREIGN_KEY)
private File brandLogoLarge;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = COLUMN_CONTACT_PERSONS, nullable = true)
private List<BrandContactPerson> contactPersons;
#Column(name = COLUMN_OTHER_DETAILS, columnDefinition = "VARCHAR(255)", nullable = true)
private String otherDetails;
#Column(name = COLUMN_BRAND_STATUS, columnDefinition = "TINYINT(1) DEFAULT 1", nullable = false)
private int status;
#Column(name = BRAND_ADDED_BY_FOREIGN_KEY, nullable = true)
private int createdBy;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = COLUMN_BRAND_ADDED_ON, columnDefinition = "DATETIME", nullable = false)
private Date createdDate;
#Column(name = BRAND_MODIFIED_BY_FOREIGN_KEY, nullable = true)
private int updatedBy;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = COLUMN_BRAND_MODIFIED_ON, columnDefinition = "DATETIME", nullable = true)
private Date updatedDate;
#OneToOne(cascade = CascadeType.MERGE)
#JoinColumn(name = COLUMN_CLASSIFICATION)
private Classification classification;
//Setter Getter
}
Service Impl Class
#Repository
public class BrandCustomRepositoryImpl implements BrandCustomRepository {
#Autowired
private BrandQueryDslRepository brandQueryDslRepository;
#Autowired
private EntityManager em;
#Override
public List<Brand> search(BrandSearchModel searchQuery) {
JPAQuery<Contract> query = new JPAQuery<>(em);
QBrand qBrand = QBrand.brand;
BooleanBuilder builder = new BooleanBuilder();
if (searchQuery.getPageNo() == null) {
searchQuery.setPageNo(0);
}
if (searchQuery.getPageSize() == null) {
searchQuery.setPageSize(UserSearchModel.DEFAULT_PAGE_SIZE);
}
prepareBrandSearchBuilder(builder, qBrand, searchQuery);
builder.and(qBrand.status.eq(Constant.ACTIVE));
List<Brand> brand1 = query.from(qBrand.brand).where(builder).offset(0).limit(20)
.select(Projections.bean(Brand.class, qBrand.brandName,qBrand.contactPersons))
.fetch();
return brand1;
}
This is the above example. Thanks in advance.
I am new to Hibernate. I have two tables Team(parent) and Product(child) with TEAM_ID column as a relationship, each team will have multiple products and each product will have single team. I have created entity classes with #OneToMany mapping in Team class and #ManyToOne in Product class.
I need to coverup below scenarios,
To save both product and team when team is new
Save only product if the team is already available
When i am trying to save product it tries to save team again throws constraint error.
Please help.
Team:
#Entity
#Table(name = "TEAM")
public class Team implements Serializable{
private static final long serialVersionUID = 5819170381583611288L;
#Id
#SequenceGenerator(name="teamIdSeq",sequenceName="team_id_seq",allocationSize=1)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="teamIdSeq")
#Column(name="TEAM_ID", updatable = false, nullable = false, unique = true)
private int teamId;
#Column(name="NAME", nullable = false, unique = true)
private String teamName;
#Column(name="DESCRIPTION", nullable = false)
private String teamDesc;
#Column(name="CONTACTS", nullable = false)
private String contacts;
#Column(name="APPROVER_NAME", nullable = false)
private String approverName;
#Column(name="APPROVAL_STATUS", nullable = false)
private int approvalStatus;
#Temporal(TemporalType.DATE)
#Column(name="CREATED_ON", nullable = false)
private Date createdOn;
#Column(name="CREATED_BY", nullable = false)
private String createdBy;
#Temporal(TemporalType.DATE)
#Column(name="MODIFIED_ON", nullable = false)
private Date modifiedOn;
#Column(name="MODIFIED_BY", nullable = false)
private String modifiedBy;
#OneToMany(fetch = FetchType.LAZY, mappedBy="team", cascade = CascadeType.ALL)
private Set<Product> products;
//setters and getters
}
Product:
#Entity
#Table(name = "PRODUCT", uniqueConstraints = {#UniqueConstraint(columnNames = {"PRODUCT_ID", "TEAM_ID"})})
public class Product implements Serializable{
private static final long serialVersionUID = 5819170381583611288L;
#Id
#SequenceGenerator(name="productIdSeq", sequenceName="product_id_seq",allocationSize=1)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="productIdSeq")
#Column(name="PRODUCT_ID", updatable = false, nullable = false)
private int productId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "TEAM_ID")
private Team team;
#Column(name="NAME", nullable = false, unique = true)
private String productName;
#Column(name="DESCRIPTION", nullable = true)
private String productDesc;
#Column(name="APPROVER_NAME", nullable = false)
private String approverName;
#Column(name="APPROVAL_STATUS", nullable = false)
private int approvalStatus;
#Temporal(TemporalType.DATE)
#Column(name="CREATED_ON", nullable = false)
private Date createdOn;
#Column(name="CREATED_BY", nullable = false)
private String createdBy;
#Temporal(TemporalType.DATE)
#Column(name="MODIFIED_ON", nullable = false)
private Date modifiedOn;
#Column(name="MODIFIED_BY", nullable = false)
private String modifiedBy;
#OneToMany(fetch = FetchType.LAZY, mappedBy="product")
private Set<Form> forms;
//setters and getters
}
DAO:
#Repository
#EnableTransactionManagement
public class KMDBDAOImpl implements KMDBDAO {
#Autowired
private SessionFactory sessionFactory;
public void addTeam(Team team) {
Product product = new Product(team, "BMA" + Math.random(), "UI Tool", "test",
1, new Date(), "test", new Date(), "test");
Set<Product> products = new HashSet<Product>();
products.add(product);
team.setProducts(products);
if(getTeam(team.getTeamName()) != null) {
product.setTeam(getTeam(team.getTeamName()));
sessionFactory.getCurrentSession().saveOrUpdate(product);
} else {
sessionFactory.getCurrentSession().saveOrUpdate(team);
}
}
public Team getTeam(String teamName) {
Query query = sessionFactory.getCurrentSession().createQuery("from Team where teamName = :name");
query.setString("name", "teamName");
return (query.list().size() > 0 ? (Team) query.list().get(0) : null);
}
The only time that you should set Product list on Team is when Team is a new entity. So:
Set<Product> products = new HashSet<Product>();
products.add(product);
if(getTeam(team.getTeamName()) != null) {
product.setTeam(getTeam(team.getTeamName()));
sessionFactory.getCurrentSession().saveOrUpdate(product);
} else {
team.setProducts(products);
sessionFactory.getCurrentSession().saveOrUpdate(team);
}
i give you some example code for one to many relationship please go through it and let me kn if some problem .... i have 2 tables 1.product 2.sku my condition is , one product have many sku's ...
Product.java
#LazyCollection(LazyCollectionOption.FALSE)
#ElementCollection(targetClass=Product.class)
#OneToMany(mappedBy="product" , cascade=CascadeType.MERGE)
private List<Sku> listSkuOrders = new ArrayList<>();
Sku.java
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = PRODUCT_ID , nullable = false)
private Product product;