I have two Eclipse Projects with two Entities (Customer and Cart).
Projekt CustomerMicroService:
#Entity
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int customerId;
private String name;
private String address;
#OneToOne
#JoinColumn(name = "cart_test")
private Cart cart;
public Customer(Cart cart) {
this.cart = cart;
Project CartMicroService:
#Entity
public class Cart {
#Id
#JoinColumn(name = "cart_id")
private int cartId;
private Map<Integer, CartItem> cartItems;
private int numberOfArticles;
public Cart() {
cartItems = new HashMap<Integer, CartItem>();
numberOfArticles = 0;
}
I am getting this error:
org.hibernate.AnnotationException: #OneToOne or #ManyToOne on de.leuphana.customer.component.behaviour.Customer.cart references an unknown entity: de.leuphana.cart.component.behaviour.Cart
How do I connect those two Entities? I am expecting something like this in my Database:
<item>
<customerId>1000</customerId>
<name>name</name>
<address>email#email.com</address>
<cart_test>Cart</cart_test>
<!-- OR something like -->
<cart_id>CartId</cart_id>
This is my Spring Boot Application:
#SpringBootApplication
public class CustomerApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerApplication.class, args);
}
}
You cannot do this. Hibernate expects used model to be mapped. Mapping it in other project doesn't give any error to the outer world as it can be sealed in any way.
The workaround would be to define your model in some module, that would be shared by your projects.
Related
I created the following models:
"Vendor"
"PickupStation"
And both of them have a OneToMany Relationship to a composite Key
"PickupStationVendorDetails" which has an embedded Id "PickupStationVendorKey"
It works to save the "PickupStationVendorDetails" with the corresponding Vendor and PickupStation but when I want to fetch them from e.g the Vendor nothing is found.
Vendor.java
#Entity
public class Vendor {
...
#OneToMany(mappedBy = "vendor")
private Set<PickupStationVendorDetails> pickupStations;
}
PickupStation.java
#Entity
public class PickupStation {
#OneToMany(mappedBy = "pickupStation")
private Set<PickupStationVendorDetails> vendors;
}
PickupStationVendorDetails.java
#Entity
public class PickupStationVendorDetails {
#EmbeddedId
private PickupStationVendorKey id;
#ManyToOne
#MapsId("vendorId")
#JoinColumn(name = "vendor_id")
private Vendor vendor;
#ManyToOne
#MapsId("pickupStationId")
#JoinColumn(name = "pickup_station_id")
private PickupStation pickupStation;
}
PickupStationVendorKey.java
#Embeddable
public class PickupStationVendorKey implements Serializable {
#Column(name = "vendor_id", columnDefinition = "BINARY(16)")
private UUID vendorId;
#Column(name = "pickup_station_id")
private Long pickupStationId;
public PickupStationVendorKey() {
}
public PickupStationVendorKey(UUID vendorId, Long pickupStationId) {
this.vendorId = vendorId;
this.pickupStationId = pickupStationId;
}
....
}
How I persist the entities:
At first I create the embeddedID and save the details via repository:
PickupStationVendorDetails pickupStationVendorDetails = new PickupStationVendorDetails();
pickupStationVendorDetails.setVendor(vendor);
pickupStationVendorDetails.setPickupStation(pickupStation);
pickupStationVendorDetails.setDeliveryDays(relationship.getDeliveryDays());
PickupStationVendorKey embeddedId = new PickupStationVendorKey(vendor.getId(),pickupStation.getId());
pickupStationVendorDetails.setId(embeddedId);
PickupStationVendorDetails d = pickupStationVendorDetailsRepository.save(pickupStationVendorDetails);
Afterwards I add them to the Set<> of the corresponding Entities and save them too.
vendor.getPickupStations().add(d);
pickupStation.getVendors().add(d);
vendorService.save(vendor);
pickupStationRepository.save(pickupStation);
And when I try to call vendor.getPickupStations() there seems to be no relationship.
Except I call pickupStationVendorDetailsRepository.findAll() the composite Key is correctly persisted and saved, and from there on I would be able to get the PickupStation and the Vendor. But that's not how it should work I guess.
Am I missing something?
I'm currently developing my project under Spring with JPA.
First off, here is my database schema for the background information
So, I'm undergoing difficulties when I try to use history_id of HISTORY as the primary key of TAG. It gives me ...Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: This class [class com.wrapsody.demo.HistoryTag] does not define an IdClass error.
So I added #IdClass(HistoryTag.HistoryTagAssignId.class) in my HistoryTag.java
#NoArgsConstructor(access = AccessLevel.PROTECTED) #Data #Entity
#IdClass(HistoryTag.HistoryTagAssignId.class)
public class HistoryTag implements Serializable {
#Id
#ManyToOne
private History history;
#Column
private String tagName;
#Builder
public HistoryTag(String tagName) {
this.tagName = tagName;
}
#NoArgsConstructor
public static class HistoryTagAssignId implements Serializable {
private History history;
public HistoryTagAssignId(History history) {
this.history = history;
}
}
}
For the reference, this is History.java
#NoArgsConstructor(access = AccessLevel.PROTECTED)
#Data
#Entity
public class History {
#Id
#GeneratedValue
private Long historyId;
#Column
private String historyMaterName;
#Column
private String historyFreeSetName;
History(String historyMaterName, String historyFreeSetName) {
this.historyMaterName = historyMaterName;
this.historyFreeSetName = historyFreeSetName;
}
}
Any guidance towards solving this error msg is appreciated.
Thanks!
For tag table you dont need entity class. Its duable in History entity with:
#ElementCollection
#CollectionTable(
name="TAG",
joinColumns=#JoinColumn(name="HISTORY_ID")
)
#Column(name="TAG_NAME")
List<String> tags;
https://en.wikibooks.org/wiki/Java_Persistence/ElementCollection#Basic_Collections
I have a problem using JPA and RelationsShips One to Many with Jackson and Spring Rest ... I try to find multiples solutions but anything is working for me , and I don't kno where is the problem.
For example I have a table Team that has One to Many/Many To One relationship
I have two repository one for Team and another for Player
Team >>> has Many >> Player
Player >>> many to one >> Team
My entity Team has the following content
#Entity
#Table(name = "teams")
#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class Team {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private long teamId;
private String abbreviation;
private String team;
private String simpleName;
private String logo;
#OneToMany(cascade = {CascadeType.ALL,CascadeType.PERSIST,CascadeType.MERGE}, mappedBy = "team")
#Column(nullable = false)
private List<Player> players;
Theirs getters/setter , hashcodes and string similars.
On the other hand the entity Player
#Entity
#Table(name = "player")
#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class Player {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "teams_id", nullable=true)
private Team team;
private String name;
So , I have the typical get call in a controller in a repository.
#RestController
#RequestMapping("/api/public/team")
public class TeamController {
#Autowired
private TeamRepository teamRepository;
#Autowired
private GenericMethods genericMethods;
#GetMapping(value = "/{id}")
public Team getPersona(#PathVariable("id") int id) {
return teamRepository.findOne(genericMethods.toLong(id));
}
And repository
#Repository
public interface TeamRepository extends JpaRepository<Team, Long> {
}
Now , when I call this endpoint I receive the following answer and I think that is incorrect , I only need a List With Players
{
"id":2,
"teamId":0,
"abbreviation":null,
"team":null,
"simpleName":"Betis",
"logo":null,
"players":[
{
"id":1,
"team":2,
"category":{
"id":1,
"nombre":"juvenil a",
"language":null,
"description":null,
"league":[
],
"players":[
1,
{
"id":2,
"team":2,
"category":1,
"name":"hulio"
}
]
},
"name":"pepe"
},
2
]
}
I need to acces at information with Player and Team so I can't use #JsonIgnoreProperties
Could anyone help to solve this problem ?
Depending on what you really want to achieve you may try different options. I'm not sure if you're using (or intending to use) spring-data-rest or not.
1. Dedicated repository
Spring data rest will embed the related entities if they don't have their own repository. Try creating public interface PlayersRepository extends JpaRepository...
2. Lazy loading
Why are you using FetchType.EAGER ? Try without it.
3. Projections
Projections are only applicable to lists, not to individual entities (i.e. not explicitly what you're asking for). You can hide players from the Teams collection even if it was returned by default like so:
#Projection(name = "noPlayers", types = { Team.class })
public interface TeamWithoutPlayers {
Long getId();
long getTeamId();
String getAbbreviation();
String getTeam();
String getSimpleName();
String getLogo();
}
More info - Spring Data Rest Projections
4. Ignore during serialization in Team Entity using #JsonIgnore
#JsonIgnore
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "teams_id", nullable=true)
private Team team;
Final thought
With spring-data-rest you can extend a CrudRepository instead of JpaRepository and access the item directly through the repository. That way you don't need to write a controller.
We have Spring Boot 2.x, Spring Data and PostgreSQL as database.
In our application we have Driver class as below
#Data
#Entity
public class Driver {
private String id;
private String name;
private String licenseNo;
}
Now a car can be driven by many drivers. So we have Car class as below.
#Data
#Entity
public class Car {
private String id;
private String number;
private String registrationNumber;
#OneToMany(fetch = FetchType.LAZY)
private List<Driver> drivers;
}
Whenever we fetch drivers from car object we get drivers not ordered by id in ascending, seems like it orders by name or id in descending order.
Is there any way in JPA where we can specify the default order by when we map.
Thanks
Hi,you add a annotation in drivers field.
show code.
#Data
#Entity
public class Car {
private String id;
private String number;
private String registrationNumber;
#javax.persistence.OrderBy("id ASC")
#OneToMany(fetch = FetchType.LAZY)
private List<Driver> drivers;
}
order option`s 'ASC' 'DESC',default is ASC
exsmple:
#javax.persistence.OrderBy("id")
#javax.persistence.OrderBy("name")
or:
#javax.persistence.OrderBy("id DESC")
#javax.persistence.OrderBy("name DESC")
I have the following class structure:
public class Container {
private Set<Child> childs = new HashSet<>();
}
public class Child {
String name;
String value;
String param;
}
Because of Container class is going to be single in application (just wrapper on collections that may be updated), I would like to store it in single table, e.g."childs" with columns
id | name | value | param
Is it possible to make such mapping in order to use Container when fetch or
store it through hb session with corresponding updates to childs collection:
getSession().saveOrUpdate(container)
And if so, what mapping should be in that case?
UPD: I was going to have 2 classes mapped to single table
After some research I ended up with such solution:
#Entity
#Table(name = "childs")
public class Container {
#Id
//optional your id strategy
#GeneratedValue(strategy = GenerationType.AUTO, generator = "xyz")
Long id;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name="childs", joinColumns=#JoinColumn(name="id"))
private Set<Child> childs = new HashSet<>();
}
#Embeddable
public class Child {
String name;
String value;
String param;
}
table structure - childs(id, name, value, param)
im not sure about the getSession().saveOrUpdate(container) , but the mapping for you problem should look something like this.
#Entity
public class Container {
#ManyToOne
private Set<Child> childs = new HashSet<>();
}
#Entity
public class Child {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long id;
String name;
String value;
String param;
}