I have two entities: Dealers and Makes. Dealers have multiple makes.I am able to insert the records as a one-to-many relationship between these two entities.
However, I am not able to retrieve the records based on dealer ID. I tried many different ways and it's still throwing this exception: Property not found make(it is table) of : class name(full classname)
If anyone could provide me with some hints, it would be greatly appreciated.
Dealer:
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.OneToMany;
import javax.persistence.JoinTable;
import javax.persistence.CascadeType;
import javax.persistence.JoinColumn;
#Entity
#Table(name = "dealer")
public class Dealer implements java.io.Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
public Dealer(){
}
public Dealer(String DealerName,String dealerPhno,Set makes){
this.dealerName=DealerName;
this.dealerphno=dealerPhno;
this.dealerMakes=makes;
}
public void setDealerMakes(Set<Make> dealerMakes) {
this.dealerMakes = dealerMakes;
}
#Id
#GeneratedValue
#Column(name = "dealer_id")
private long dealerId;
public long getDealerId() {
return dealerId;
}
public void setDealerId(long dealerId) {
this.dealerId = dealerId;
}
public String getDealerName() {
return dealerName;
}
public void setDealerName(String dealerName) {
this.dealerName = dealerName;
}
public String getDealerphno() {
return dealerphno;
}
public void setDealerphno(String dealerphno) {
this.dealerphno = dealerphno;
}
#Column(name = "dealer_name" ,unique=true, nullable = false, length=20)
private String dealerName;
#Column(name = "dealer_phno" , nullable = false, length=20)
private String dealerphno;
#OneToMany(cascade = CascadeType.ALL)
//#OneToMany(fetch=FetchType.EAGER)
#JoinColumn(name="dealer_id", nullable=false)
//#JoinTable(name = "dealer_make", joinColumns = { #JoinColumn(name = "dealer_id") }, inverseJoinColumns = { #JoinColumn(name = "make_id") })
private Set<Make> dealerMakes = new HashSet<Make>(0);
public Set<Make> getDealerMakes() {
return dealerMakes;
}
}
Make
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Entity;
import javax.persistence.Table;
#Entity
#Table(name = "make")
public class Make implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 2L;
public Make(){
}
public Make(String makeName,String modelName,String price){
this.makeName=makeName;
this.modelName=modelName;
this.price=price;
}
public long getMakeId() {
return makeId;
}
public void setMakeId(long makeId) {
this.makeId = makeId;
}
public String getMakeName() {
return makeName;
}
public void setMakeName(String makeName) {
this.makeName = makeName;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
#Id
#GeneratedValue
#Column(name = "make_id")
private long makeId;
#Column(name = "make_name" , nullable = false, length=8)
private String makeName;
#Column(name = "model_name" , nullable = false, length=8)
private String modelName;
#Column(name = "price" , nullable = false, length=8)
private String price;
}
Query I tried:
Criteria dealer=sessionFactory.getCurrentSession().createCriteria(Dealer.class);
Criteria make=dealer.createCriteria(make);
make.add(Restrictions.gt("dealerId",new Long(dealerId)));
List<Dealer> results=dealer.list(); //throwing exception
Ouput i am expecting:
Dealer_Id dealername phonenumber
1 halal 074563485
Make has below records:
make_id makename makeprice dealer_id
1 ford 3000$ 1
2 hyundai 2000$ 1
I want results like dealer details with make details.
OK. So you want to load dealers with their makes, and you only want the dealers having an ID greater than a given ID.
First of all, you could just load dealers. The list of their makes would automatically be loaded by Hibernate when you would call getDealerMakes():
Criteria c = session.createCriteria(Dealer.class);
c.add(Restrictions.gt("dealerId", dealerId)); // let's say delerId = 6
List<Dealer> dealers = c.list(); // execute SQL query select d.* from dealer d where d.dealer_id > 6
for (Dealer dealer : dealers) {
Set<Make> make = dealer.getDealerMakes() // execute SQL query select m.* from make m where m.dealer_id = <theIdOfTheCurrentDealer>
}
This has the disadvantage of executing N + 1 queries.
So if you want to load the dealers and their makes in a single query, you need to set a fetch mode so that the makes are loaded. Note that since the join uses the association that you defined between Dealer and Make, you don't need to tell Hibernate that the ID of the dealer table must be equal to the dealer_id of the make table: Hibernate already knows that thanks to the JoinColumn annotation that you put on the association. The query is thus the following:
Criteria c = session.createCriteria(Dealer.class);
c.add(Restrictions.gt("dealerId", dealerId));
// this tells Hibernate that the makes must be fetched from the database
// you must use the name of the annotated field in the Java class: dealerMakes
c.setFetchMode("dealerMakes", FetchMode.JOIN);
// Hibernate will return instances of Dealer, but it will return the same instance several times
// once per make the dealer has. To avoid this, you must use a distinct root entity transformer
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
List<Delaer> dealers = c.list(); // executes the SQL query:
// select d.*, m.* from dealer d left join make m on d.dealer_id = m.dealer_id where d.dealer_id > 6
for (Dealer dealer : dealers) {
Set<Make> make = dealer.getDealerMakes() // no SQL query. The makes are already loaded
}
criteria.setFetchMode("dealerMakes", FetchMode.JOIN);
criteria.createCriteria("dealerMakes");
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
This do the trick!
public List<Dealer> findDealers() {
Criteria dealer=sessionFactory.getCurrentSession().createCriteria(Dealer.class);
Criteria make=dealer.createCriteria(make);
make.setFetchMode("dealer", FetchMode.JOIN);
make.add(Restrictions.gt("dealerId",new Long(dealerId)));
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); // depends on wat u want
return criteria.list();
}
try to return like this, hope it works, let me know if there is more to it
Related
I am trying to use Hibernate for the first time, so I am not very familiar with the syntax yet. I am trying to model a library system. The classes that are causing problem are "Borrow" and "CopyBook" which are as following:
import javax.persistence.*;
#Entity
#Table(name = "copybook", schema="project")
public class CopyBook {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="copy_id", unique = true, nullable = false)
private int copyId;
#Convert(converter = StatusAttributeConverter.class)
#Column(name="status", columnDefinition = "TEXT DEFAULT 'AVAILABLE'")
private Status status;
#ManyToOne(optional = false)
#JoinColumn(name = "book_id")
private Book book;
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
#OneToOne(mappedBy = "copy")
private Borrow borrow;
public Borrow getBorrow() {
return borrow;
}
public void setBorrow(Borrow borrow) {
this.borrow = borrow;
}
#OneToOne(mappedBy = "copy", optional = false)
private Order order;
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import javax.persistence.*;
import java.util.Date;
#Entity
#Table(name = "borrow", schema = "project")
public class Borrow {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="no_borrow", unique = true, nullable = false)
private int noBorrow;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="date_borrow", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP", insertable = false, updatable = false, nullable = false)
private Date dateBorrow;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="date_return")
private Date dateReturn;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="max_date_return", insertable = false, updatable = false)
private Date maxDateReturn;
#OneToOne(optional = false)
#JoinColumn(name = "copy_id")
#NotFound(action = NotFoundAction.IGNORE)
private CopyBook copy;
public CopyBook getCopy() {
return copy;
}
public void setCopy(CopyBook copy) {
this.copy = copy;
}
#ManyToOne(optional = false)
#JoinColumn(name="mem_id")
private Members member;
public Members getMember() {
return member;
}
public void setMember(Members member) {
this.member = member;
}
}
I am using IntelliJ, so when I try to run the query of the Borrow entity it showed me that it cannot find CopyBook with id 1 even though it actually exists in the database
This is the entries currently present in my database (In these two table)
CopyBook:
Borrow:
As we can see, there is indeed a CopyBook with id of 1. This is also proved when I run the query of CopyBook entity which successfully returned all the results
Result after running in JPA select entity from CopyBook entity
Just to see what results Borrow is actually giving, I have added #NotFound(action = NotFoundAction.IGNORE). And this is the result I get
So I found this is a very bizarre situation because all data exist, and CopyBook is able to find its correspondent Borrow. But Borrow is unable to find its correspondent CopyBook ?
Strangley, I have another entity class Order which has almost the same attributes (Also has a OneToOne relationship with CopyBook), and it works perfectly.
Problem Solved.
Because I have multiple One-To-Many relationship, and the FetchType is by default Eager. Whenever I want to retrieve the entity, it will perform Left Outer Join for all the entities until the end.
However, under the scope of this context. A book does not have to be ordered to exist in the library, be performing "JOIN" it loses entries and therefore causes the aforementioned problem.
As a result, all I did was to set the attributesOrder and Borrow with optional = true and fetch = Fetchtype.Lazy so it will not perform join unless necessary
I have added Hibernate filters on my entities . These filters are applied on queries which fetch Collection of entity but not applied on queries which fetch single entity. Below is my code.
AOrganization.java
#MappedSuperclass
#FilterDef(name = "OrgFilter", parameters = { #ParamDef(name = "allowedOrgIdList", type = "long") })
#Filter(name = "OrgFilter", condition = "org_id in (:allowedOrgIdList)")
public class AOrganization implements Serializable {
#ManyToOne()
#JoinColumn(name = "org_id", nullable = true)
private Organization organization;
public Organization getOrganization() {
return organization;
}
public void setOrganization(Organization organization) {
this.organization = organization;
}
}
Site.java
#Data
#Entity
#Table(name = "site")
public class Site extends AOrganization{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private long id;
#Column(name = "site_name")
private String siteName;
#Override
public String toString() {
return "Site [id=" + id + ", siteName=" + siteName + "]";
}
}
SiteService.java
public interface SiteService {
public List<Site> getAllSites();
public List<Site> getSiteBySiteName(String siteName);
public Site updateSiteName(Long id, String siteName);
}
SiteRepository.java
#Repository
public interface SiteRepository extends AOrganizationRepository<Site, Long> {
public List<Site> findBySiteName(String siteName);
public List<Site> findByOrganization_Id(Long orgId);
}
AOrganizationRepository.java
#NoRepositoryBean
public interface AOrganizationRepository<T, ID extends java.io.Serializable> extends CrudRepository<T, ID> {
}
SiteServiceImpl.java
#Service
public class SiteServiceImpl implements SiteService {
#Autowired
private EntityManager entityManager;
#Autowired
private SiteRepository siteRepository;
#Override
public List<Site> getAllSites() {
Iterable<Site> sites = siteRepository.findAll();
List<Site> allSites = new ArrayList<>();
sites.forEach(allSites::add);
return allSites;
}
#Override
public List<Site> getSiteBySiteName(String siteName) {
List<Site> allSites = siteRepository.findBySiteName(siteName);
return allSites;
}
#Override
public Site updateSiteName(Long id,String siteName) {
Site site = siteRepository.findById(id).get();
if(site == null)
return null;
site.setSiteName(siteName);
siteRepository.save(site);
return site;
}
}
AOrganizationAspect.java
#Aspect
#Component
#Slf4j
public class AOrganizationAspect {
#PersistenceContext
private EntityManager entityManager;
#Pointcut("execution(public * com.harshal.springboot.springfilter.repository.AOrganizationRepository+.*(..))")
protected void aOrganizationRepositoryRepositoryMethod() {
log.info("aOrganizationRepositoryRepositoryMethod");
}
#Around(value = "aOrganizationRepositoryRepositoryMethod()")
public Object enableOwnerFilter(ProceedingJoinPoint joinPoint) throws Throwable {
// Variable holding the session
Session session = null;
try {
// Get the Session from the entityManager in current persistence context
session = entityManager.unwrap(Session.class);
// Enable the filter
Filter filter = session.enableFilter("OrgFilter");
// Set the parameter from the session
List<Long> orgList = getAllowedOrgIdList();
filter.setParameterList("allowedOrgIdList", orgList);
} catch (Exception ex) {
// Log the error
log.error("Error enabling OrgFilter : Reason -" + ex.getMessage());
}
// Proceed with the joint point
Object obj = joinPoint.proceed();
// If session was available
if (session != null) {
// Disable the filter
session.disableFilter("OrgFilter");
}
// Return
return obj;
}
private List<Long> getAllowedOrgIdList() {
return Arrays.asList(2l);
}
}
So , hibernate filters are applied if method getSiteBySiteName is called and filters are not applied if findById method is called.
Below are queries :
For getSiteBySiteName :
select site0_.id as id1_2_, site0_.org_id as org_id3_2_,
site0_.site_name as site_nam2_2_ from site site0_ where site0_.org_id
in (?) and site0_.site_name=?
Please help . Thanks in advance.
For findById
select site0_.id as id1_2_0_, site0_.org_id as org_id3_2_0_,
site0_.site_name as site_nam2_2_0_, organizati1_.id as id1_1_1_,
organizati1_.address as address2_1_1_, organizati1_.org_name as
org_name3_1_1_ from site site0_ left outer join organization
organizati1_ on site0_.org_id=organizati1_.id where site0_.id=?
findById is using the EntityManager.find method and do not create a query.
Plus Hibernate Filters only work on queries.
You should write a query instead of using findById
I was trying to add data to my tableView in my JavaFX app. I am using hibernate to do operations on my Database. I used a query to get all the orders and store each order in an object and added the object to the observable list of the tableView. I created the orders class and mapped it to my database. This is the class of the orders:
#Entity
#Table(name = "orders")
public class orders implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "order_id")
private int order_id;
#JoinColumn(name = "item_id")
#ManyToOne
#NotNull
private items item_id;
#Column(name = "quantity")
#NotNull
private int quantity;
#Column(name = "price_per_unit")
#NotNull
private double price_per_unit;
#Column(name = "total_price")
#NotNull
private double total_price;
#Column(name = "order_date")
#NotNull
private Date order_date;
#JoinColumn(name = "user_id")
#ManyToOne
#NotNull
private users user_id;
public orders() {
}
public orders(int order_id, items item_id, int quantity, double price_per_unit, double total_price, Date order_date, users user_id) {
this.order_id = order_id;
this.item_id = item_id;
this.quantity = quantity;
this.price_per_unit = price_per_unit;
this.total_price = total_price;
this.order_date = order_date;
this.user_id = user_id;
}
public int getOrder_id() {
return order_id;
}
public void setOrder_id(int order_id) {
this.order_id = order_id;
}
public items getItem_id() {
return item_id;
}
public void setItem_id(items item_id) {
this.item_id = item_id;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public double getPrice_per_unit() {
return price_per_unit;
}
public void setPrice_per_unit(double price_per_unit) {
this.price_per_unit = price_per_unit;
}
public double getTotal_price() {
return total_price;
}
public void setTotal_price(double total_price) {
this.total_price = total_price;
}
public Date getOrder_date() {
return order_date;
}
public void setOrder_date(Date order_date) {
this.order_date = order_date;
}
public users getUser_id() {
return user_id;
}
public void setUser_id(users user_id) {
this.user_id = user_id;
}
}
And the below code is the code of the view in which I have the tableView that loads the orders and displays the orders from the database:
public class OrdersPageController implements Initializable {
private Main app;
private Session session;
private Transaction transaction = null;
#FXML
private TableView<orders> table;
public void setApp(Main app) {
this.app = app;
}
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
//Fill the table view
getOrders();
}
public void goBack(ActionEvent event){
session.close();
transaction = null;
app.goToHomePage();
}
public void processLogout(ActionEvent event){
session.close();
transaction = null;
app.userLogout();
}
public void addOrder(ActionEvent event){
session.close();
transaction = null;
app.addOrdersPage();
}
public void deleteOrder(ActionEvent event){
session.close();
transaction = null;
app.closeOrdersPage();
}
public void getOrders(){
try{
String hql = "FROM orders";
Query query = session.createQuery(hql);
List<orders> list = query.getResultList();
for (orders o : list) {
//Create an order object
orders order = new orders();
order.setOrder_id(o.getOrder_id());
order.setItem_id(o.getItem_id());
order.setPrice_per_unit(o.getPrice_per_unit());
order.setQuantity(o.getQuantity());
order.setOrder_date(o.getOrder_date());
order.setTotal_price(o.getTotal_price());
order.setUser_id(o.getUser_id());
//Create an observable list for the table
ObservableList<orders> tableList = table.getItems();
//Add the order object to the list
tableList.add(order);
//Set the created list to the table to show data
table.setItems(tableList);
}
}catch(Exception e){
System.out.println(e.getMessage());
}
finally{
session.close();
}
}
}
Note that the getOrders method is the method that gets the orders from the database and sets the observable list of the tableView.
I am having problem displaying the item_id and the user_id of the order. I think the problem is that they both are objects of type items and users respectively and the table displays the address of the objects. Instead I want to display the numbers of the ids of the item ordered and the user that made the order. If you know what I can do to fix my problem please share it with me.
Add cellFactorys to the relevant columns. You haven't shown the FXML in the question, so I don't know the names you assigned to the appropriate TableColumn instances, but you can do something like this:
public class OrdersPageController implements Initializable {
// ...
#FXML
private TableView<orders> table;
#FXML
private TableColumn<orders, users> userColumn ;
#Override
public void initialize(URL url, ResourceBundle rb) {
userColumn.setCellFactory(tc -> new TableCell<>() {
#Override
protected void updateItem(users user, boolean empty) {
super.updateItem(user, empty);
if (empty || user == null) {
setText("");
} else {
String text = /* anything you need based on user */
setText(text);
}
}
});
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
//Fill the table view
getOrders();
}
}
Just override toString method in users and items Classes:
Example: in your users Class ->
#Override
public String toString() {
return user_id.toString();
}
As James_D stated, have a look on java conventions. Java Classes should be always be with Capital Letter.
For some reason, I need to store my data in a Map and I don't want to declare each attribute of my objectify Entity one by one.
For instance, here is what my map would look like to:
"COMPANY_NAME" -> "something"
"TURNOVER_Min" -> 1000000 (a long value)
"CLIENT_STATUS"-> true (a boolean value)
And I would like to perform queries like that :
List<Lead> leads = ofy().load().type(Lead.class).filter("data.NET_INCOME_MIN >", 5.0).filter("data.NET_INCOME_MAX <", 100.0).list();
But I am getting no results although some data match this query...
I must tell you that it works for one filter at a tome...
It also works for several filters with "=" :
Here is my entity:
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Index;
#Entity
public class Lead implements Serializable {
private static final long serialVersionUID = 5920146927107230150L;
#Id
private String url;
#Index
private Date dateCreated;
#Index
private Map<String, Object> data = new HashMap<>();
public Lead() {}
public Lead(String url) {
this.url = url;
this.dateCreated = new Date();
}
public void addData(String key, Object value) {
data.put(key, value);
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
public Map<String, Object> getData() {
return data;
}
public void setData(Map<String, Object> data) {
this.data = data;
}
}
Thank you very much
This is not your fault and not Objectify problem either.
As per the datastore documentation:
Inequality filters are limited to at most one property
To do what you want to do :
Use the first filter to retrieve only the keys of the entities ( use .keys() instead of .list() ).
Use the second filter to retrieve only the keys of the entities.
To perform the ANDing you need to get the intersection of the two key sets retrieved above.
Now as you have the keys of the entities you want and you can fetch the entities with a batch get operation.
I have entities like this : User->Blague->Score where an user have numerous blagues(childs) and a blague have one score.
I'm trying to get the score from a blague, but when I write this :
User userPoster = ofy().load().type(User.class).id(5066549580791808L).now();
Blague blague = ofy().load().type(Blague.class).parent(userPoster).id(4609152743636992L).now();
Score score = ofy().load().type(Score.class).parent(blague).id(5735052650479616L).now();
resp.getWriter().println(userPoster);
resp.getWriter().println(blague);
resp.getWriter().println(score);
(The ids are corrects) score is null, unlike blague and userPoster. Why is it null ?
The entities are created like that :
#ApiMethod(
name = "addBlague",
path = "addBlague",
httpMethod = ApiMethod.HttpMethod.POST)
public void addBlague(
#Named("category") EnumCategory category,
#Named("type") EnumType type,
#Named("lenght") EnumLenght lenght,
#Named("keywords") List<String> keywords,
#Named("text") String text,
#Named("userId") Long userId){
Key<User> userKey = Key.create(User.class, userId);
Blague blague = new Blague(category, type, lenght, text, userKey);
ofy().save().entity(blague).now();
Key<Blague> blagueKey = Key.create(Blague.class, blague.getId());
Score score = new Score(0, 0, blagueKey);
ofy().save().entity(score).now();
for (String word : keywords) {
KeyWord keyword = new KeyWord(word, blagueKey);
ofy().save().entity(keyword);
}
}
and of course, the classes are registered.
How can I get the score from a blague ?
Thanks
Edit :
The Socre code :
package blagueur;
import java.util.HashMap;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Index;
import com.googlecode.objectify.annotation.Parent;
#Entity
#Index
#Cache
public class Score {
#Id
private Long id;
private int likes;
private int dislikes;
private HashMap<String, Boolean> voters;
#Parent
private Key<Blague> blagueKey;
private Score() {}
public Score(int likes, int dislikes, Key<Blague> blague) {
this.likes = likes;
this.dislikes = dislikes;
this.blagueKey = blague;
this.voters = new HashMap<String, Boolean>();
}
public Long getId() {
return id;
}
public int getLikes() {
return likes;
}
public int getDislikes() {
return dislikes;
}
public void addVote(Long userId, boolean like){
voters.put(String.valueOf(userId), like);
if (like){
likes++;
}
else{
dislikes++;
}
}
public void removeVote(Long userId){
String id = String.valueOf(userId);
boolean like = voters.get(String.valueOf(userId));
voters.remove(String.valueOf(userId));
if (like){
likes--;
}
else{
dislikes--;
}
}
public Key<Blague> getBlagueKey() {
return blagueKey;
}
}
You need to be very careful to maintain the key hierarchy.
You state that your intended entity hierarchy is User -> Blague -> Score, but this code below does not do that:
Key<User> userKey = Key.create(User.class, userId);
Blague blague = new Blague(category, type, lenght, text, userKey);
ofy().save().entity(blague).now();
Key<Blague> blagueKey = Key.create(Blague.class, blague.getId());
Score score = new Score(0, 0, blagueKey);
ofy().save().entity(score).now();
When you create the blagueKey, you do not use the userKey as the parent.
While I do not encourage the code style you have written, if you wanted to do so, you need to do this:
...
Key<Blague> blagueKey = Key.create(userKey, Blague.class, blague.getId());
...
In general, you should let objectify handle this for you by using Ref<User>, Ref<Blague> as the #Parent objects, or if you must create Key objects, use Key.create(T pojo) rather than managing Keys yourself.