404 when adding new methods to RESTful web service - java

The application works well with the generated methods and classes, but I wanted to get a list of article that matching a specific idChapitre. I get a "HTTP Status 404 - Not Found" on my browser.
This is the facade class, where I have put in the findByIdChapitre method:
#Stateless
#Path("articles")
public class ArticleFacadeREST extends AbstractFacade<Article> {
#PersistenceContext(unitName = "PNC-BackendPU")
private EntityManager em;
public ArticleFacadeREST() {
super(Article.class);
}
#GET
#Path("bychapitre/{idChapitre}")
#Produces({"application/json"})
public List<Article> findByIdChapitre(#PathParam("idChapitre") Chapitre idChapitre) {
Query q = em.createNamedQuery("Article.findByIdChapitre");
q.setParameter("idChapitre", idChapitre);
return q.getResultList();
}
...
}
and my article class:
#Entity
#Table(name = "article")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Article.findAll", query = "SELECT a FROM Article a"),
#NamedQuery(name = "Article.findByIdArticle", query = "SELECT a FROM Article a WHERE a.idArticle = :idArticle"),
#NamedQuery(name = "Article.findByIdChapitre", query = "SELECT a FROM Article a WHERE a.idChapitre = :idChapitre"),
#NamedQuery(name = "Article.findByCodeArticle", query = "SELECT a FROM Article a WHERE a.codeArticle = :codeArticle")})
public class Article implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id_article", nullable = false)
private Integer idArticle;
#Lob
#Size(max = 65535)
#Column(name = "nom_article", length = 65535)
private String nomArticle;
#Size(max = 20)
#Column(name = "code_article", length = 20)
private String codeArticle;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "idArticle")
private List<Littera> litteraList;
#JoinColumn(name = "id_chapitre", referencedColumnName = "id_chapitre", nullable = false)
#ManyToOne(optional = false)
private Chapitre idChapitre;
public Article() {
}
public Article(Integer idArticle) {
this.idArticle = idArticle;
}
Getters and setters
}
and then my chapitreclass:
....
#Entity
#Table(name = "chapitre")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Chapitre.findAll", query = "SELECT c FROM Chapitre c"),
#NamedQuery(name = "Chapitre.findByIdChapitre", query = "SELECT c FROM Chapitre c WHERE c.idChapitre = :idChapitre"),
#NamedQuery(name = "Chapitre.findByIdSection", query = "SELECT c FROM Chapitre c WHERE c.idSection = :idSection"),
#NamedQuery(name = "Chapitre.findByCodeChapitre", query = "SELECT c FROM Chapitre c WHERE c.codeChapitre = :codeChapitre")})
public class Chapitre implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id_chapitre", nullable = false)
private Integer idChapitre;
#Lob
#Size(max = 65535)
#Column(name = "nom_chapitre", length = 65535)
private String nomChapitre;
#Size(max = 20)
#Column(name = "code_chapitre", length = 20)
private String codeChapitre;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "idChapitre")
private List<Dossier> dossierList;
#JoinColumn(name = "id_section", referencedColumnName = "id_section", nullable = false)
#ManyToOne(optional = false)
private Section idSection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "idChapitre")
private List<Article> articleList;
public Chapitre() {
}
public Chapitre(Integer idChapitre) {
this.idChapitre = idChapitre;
}
Getters and setters
}

Related

Hibernate JPA #OneToMany join on 2 columns with OR statement in Entity

I have the following class:
public class Nomenclature extends BaseEntity {
#Id
#Column(name = "NOMENCLATURE_CODE")
private String nomenclatureCode;
#OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, mappedBy = "nomenclatureCode", orphanRemoval = true)
private List<Cumul> cumuls = new ArrayList<>();
}
I want to join the following Cumul class on 2 columns WHERE cumul.nomenclatureCode = nomenclature.nomenclatureCode OR cumul.nomenclatureCodeAllowedCumul = nomenclature.nomenclatureCode
public class Cumul extends BaseEntity {
#Id
#Column(columnDefinition = "NUMERIC")
#GeneratedValue(generator = "CUMUL", strategy = GenerationType.SEQUENCE)
private Long id;
#Column(name = "NOMENCLATURE_CODE")
private String nomenclatureCode;
#Column(name = "NOMENCLATURE_CODE_ALLOWED_CUMUL")
private String nomenclatureCodeAllowedCumul;
#OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL},orphanRemoval = true)
#JoinColumns(
{
#JoinColumn(name = "nomenclature_code", referencedColumnName = "nomenclature_code"),
#JoinColumn(name = "nomenclature_code_allowed_cumul", referencedColumnName = "nomenclature_code")
})
private List<Cumul> cumuls = new ArrayList<>();
Worked but this an AND statement not an OR what I was looking for

How to use In clause in JPQL query with subquery

I have a entity classes as below
ExportMO.java
#Entity
#Table(name = "DATAEXPORTTEMPLATE")
#NamedQueries({
#NamedQuery(name = "ExportTemplateMO.getTemplatesByUser", query = "SELECT DISTINCT template FROM ExportTemplateMO template " +
"join template.fields exportFields WHERE template.eId IN (SELECT S1.dcid FROM SchoolMO S1 join S1.fields S2 WHERE S2.dcid = :userDCID)")
})
public class ExportMO implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "DATATEMPLATEID", unique = true, nullable = false)
private Long templateId;
#Column(name = "EID", nullable = true)
private Long eId;
#OneToMany(fetch=FetchType.EAGER, mappedBy="templateMO", cascade={CascadeType.ALL}, orphanRemoval=true)
private Set<ExportFieldMO> fields;
}
SchoolMO.java
#Entity
#Table(name = "SCHOOLSTAFF")
public class SchoolMO implements Serializable {
#Id
#Column(name = "DCID", unique = true, nullable = false)
private Long dcid;
#Column(name = "ID", unique = true)
private Long id;
#Column(name = "USERS_DCID", unique = false, nullable = false)
#JoinColumn(name="USERS_DCID",referencedColumnName="USERS_DCID",nullable=false)
private Long users_dcid;
#OneToMany(fetch=FetchType.EAGER, mappedBy="users_dcid", cascade={CascadeType.ALL}, orphanRemoval=true)
private Set<SchoolStaffLeanMO> fields;
}
Can someone help me how to use this using the IN clause for subquery.
If i try to use the same '=' instead of 'IN' i am able to get the results.
Thanks in advance.

Deleting entity, which is element of collection and has collection of another entities in Hibernate

I have entity Ad:
#Entity
#NamedQueries({
#NamedQuery(name = "getAllAds",
query = "from Ad"),
#NamedQuery(name = "deleteById",
query = "delete from Ad where id = :id")
})
#FieldMatch(first = "initLanguage",second = "resultLanguage", message = "Languages must be different")
#Table(name = "AD_TEST")
public class Ad implements Serializable{
/**
* Version of this class in production
*/
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name = "standard", initialValue = 1)
#GeneratedValue(generator = "standard", strategy =GenerationType.SEQUENCE)
#Column(name = "AD_ID")
private long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "CLIENT",nullable = false)
private Client client;
#NotBlank
#Column(name = "AD_NAME", nullable = false)
private String name;
#NotBlank
#Column(name = "AD_DESC",nullable = false,length = 1000)
#Lob
#Size(min = 0, max = 1000)
private String description;
#Column(name = "AD_COUNTRY", nullable = false)
private String country;
#Column(name = "AD_CITY", nullable = false)
private String city;
#NotNull
/**
* Добавить проверку валидности даты
*/
#DateTimeFormat(iso = ISO.DATE,pattern = "dd.MM.yyyy")
#Column(name = "AD_END_DATE",nullable = false)
private LocalDate endDate;
#NotNull
#Column(name = "AD_INIT_LANGUAGE",nullable = false)
#Enumerated(EnumType.STRING)
private Language initLanguage;
#NotNull
#Column(name = "AD_RESULT_LANGUAGE",nullable = false)
#Enumerated(EnumType.STRING)
private Language resultLanguage;
#NotNull
#Column(name = "AD_TRANSLATE_TYPE",nullable = false)
#Enumerated(EnumType.STRING)
private TranslateType translateType;
#Lob
#Column(name = "AD_FILE")
private byte[] file;
#NotNull
#Column(name = "AD_COST",nullable = false,precision = 2)
private double cost;
#NotNull
#Column(name = "AD_CURRENCY",nullable = false)
#Enumerated(EnumType.STRING)
private Currency currency;
#Column(name = "AD_CREATING_DATE",nullable = false)
private LocalDateTime creationDateTime;
#Column(name = "AD_STATUS",nullable = false)
#Enumerated(EnumType.STRING)
private AdStatus status;
#OnDelete(action = OnDeleteAction.CASCADE)
#OneToMany(fetch = FetchType.EAGER,orphanRemoval = true,mappedBy = "ad")
#Cascade(CascadeType.ALL)
private List<ResponsedAd> responsedAds = new ArrayList<>();
public Ad(){}
/*Getters and setters, hashCode and equals*/
Ad is element of collection in Client:
#Entity
#NamedQueries({
#NamedQuery(name = "clientByEmail",
query = "from Client client where client.email = :email")
})
#Table(name = "CLIENT_TEST")
#PrimaryKeyJoinColumn(name= "client_id")
public class Client extends User{
/**
* Version of this class in production
*/
private static final long serialVersionUID = 1L;
#OneToMany(fetch = FetchType.EAGER,orphanRemoval = true,mappedBy = "client")
#Cascade(CascadeType.ALL)
public List<Ad> ads = new ArrayList<>();
#OneToMany(fetch = FetchType.EAGER,orphanRemoval = true,mappedBy = "client")
#Cascade(CascadeType.ALL)
private List<ResponsedAd> responsedAds = new ArrayList<>();
public Client(){}
Ad.class and Client.class have collection of ResponseAd objects:
#Entity
#Table(name = "RESPONSED_AD_TEST")
#NamedQueries({
#NamedQuery(name = "responsedAdsByAd",query="from ResponsedAd where ad = :ad")
})
#Component
public class ResponsedAd {
#Id
#SequenceGenerator(name = "standard", initialValue = 1)
#GeneratedValue(generator = "standard", strategy =GenerationType.SEQUENCE)
private long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "AD",nullable = false)
private Ad ad;
#Column(nullable = false)
private LocalDateTime dateTimeOfResponse;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "CLIENT")
private Client client;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "TRANSLATOR",nullable = false)
private Translator translator;
#Column(nullable = false)
#Enumerated(EnumType.STRING)
private ResponsedAdStatus status;
public ResponsedAd(){}
I want that after deleting Ad object, all ResponseAd objects from collection were deleted too.
For this I have:
public void deleteById(long id){
Ad ad = get(id);
CopyOnWriteArrayList<ResponsedAd> list = new CopyOnWriteArrayList<>(ad.getResponsedAds());
list.forEach(rad->{
Translator translator = rad.getTranslator();
translator.removeResponsedAd(rad);
ad.removeResponsedAd(rad);
Client client = rad.getClient();
client.removeResponsedAd(rad);
});
Client client = ad.getClient();
client.removeAd(ad);
}
Say me please, how can I do this right? I have very a lot of relationships and when I try do this, I get error
HTTP Status 500 - Request processing failed; nested exception is
org.springframework.dao.InvalidDataAccessApiUsageException:
deleted object would be re-saved by cascade (remove deleted object from associations):
[ua.translate.model.ad.ResponsedAd#102]; nested exception is org.hibernate.ObjectDeletedException:
deleted object would be re-saved by cascade (remove deleted object from associations): [ua.translate.model.ad.ResponsedAd#102]
First of all,
You don't need to use #NotNull if you have nullable = false already declared in #Column(nullable = false).
Second,
What you're trying to do is doing operations in Cascade. Add this cascade = CascadeType.ALL or maybe cascade = CascadeType.REMOVE to your #ManyToOne tags and it should work.
Use this as a reference: JPA #ManyToOne with CascadeType.ALL
My Client object: Client client = rad.getClient(); have two responsedAd object in collection with the same id, therefore even after deleting this responsedAd object: client.removeResponsedAd(rad); client object has one more. And now main question is why this client have two objects with the same id.

JPA persisting twice

I'm trying to save into a MySQL database a entity that looks like this:
#Entity
#Table(catalog = "logistic", schema = "")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Movement.findAll", query = "SELECT m FROM Movement m"),
#NamedQuery(name = "Movement.findByIdMovement", query = "SELECT m FROM Movement m WHERE m.idMovement = :idMovement"),
#NamedQuery(name = "Movement.findByQty", query = "SELECT m FROM Movement m WHERE m.qty = :qty"),
#NamedQuery(name = "Movement.findByDt", query = "SELECT m FROM Movement m WHERE m.dt = :dt")})
public class Movement implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id_movement", nullable = false)
private Long idMovement;
#Basic(optional = false)
#NotNull
#Column(nullable = false)
private int qty;
#Basic(optional = false)
#Column(nullable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date dt;
#JoinColumn(name = "from_id_container", referencedColumnName = "id_container", nullable = false)
#ManyToOne(optional = false, fetch = FetchType.LAZY)
private Container fromIdContainer;
#JoinColumn(name = "to_id_container", referencedColumnName = "id_container", nullable = false)
#ManyToOne(optional = false, fetch = FetchType.LAZY)
private Container toIdContainer;
#JoinColumn(name = "id_product", referencedColumnName = "id_product", nullable = false)
#ManyToOne(optional = false, fetch = FetchType.LAZY)
private Product idProduct;
#JoinColumn(name = "username", referencedColumnName = "username", nullable = false)
#ManyToOne(optional = false, fetch = FetchType.LAZY)
private User username;
// Getters and setters...
This entity has been generated by netbeans. The problem is that when I try to persist data into the database, it inserts two files instead of one. The code I use to persis the data is
Movement movement = new com.pccomponentes.sga.entity.Movement();
movement.setFromIdContainer(from);
movement.setToIdContainer(to);
movement.setIdProduct(product);
movement.setQty(obj.getInt("qty"));
movement.setUsername(userEJB.find(redis.get("token-" + token)));
movementEJB.create(movement);
What's happening?
Thank you in advance!

Hibernate: Multiple filters on an entity

I want to have multiple Hibernate filters on an entity, I have tried everything logical without luck and Google has come up short on this one, as has the Hibernate doc. I can't imagine that this is not possible. (Using Java 6 Hibernate 4.1.9.final)
Currently, I have this:
#Entity
#Table(name = "CATEGORY")
public class Category implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "CATEGORYID")
private int ID;
#Column(name = "CATEGORYNAME")
private String name;
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name = "CATEGORYID")
#OrderBy("TESTCASEID desc")
#Filter(name = "TEST_RUN_ID_FILTER")
private Collection<TestCase> testCases;
...
}
#Entity
#Table(name = "TESTCASE_NEW")
#FilterDef(name = "TEST_RUN_ID_FILTER", defaultCondition = "TESTRUNID in (:IDS)", parameters = { #ParamDef(name = "IDS", type = "int") })
public class TestCase implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "TESTCASEID")
private int ID;
#Column(name = "TESTCASENAME")
private String name;
...
}
I want to add a second independent filter to the Testcase class. What I am after is something like this:
Select ...
From CATEGORY INNER JOIN TESTCASE on CATEGORY.CATEGORYID = TESTCASE.CATEGORYID
Where TESTCASE.TESTRUNID in (....)
and TESTCASE.TESTCASENAME like '%..%'
This is what I tried
I tried adding multiple #FilterDefs to TestCase like such, but that didn't compile:
#Entity
#Table(name = "TESTCASE_NEW")
#FilterDef(name = "TEST_RUN_ID_FILTER", defaultCondition = "TESTRUNID in (:IDS)",
parameters = { #ParamDef(name = "IDS", type = "int") })
#FilterDef(name = "TESTCASE_NAME_FILTER", defaultCondition = "TESTCASENAME like :TESTCASE_NAME",
parameters = { #ParamDef(name = "TESTCASE_NAME", type = "string") })
public class TestCase implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "TESTCASEID")
private int ID;
#Column(name = "TESTCASENAME")
private String name;
...
}
The Hibernate documentation led to to try something like this which complained the testrunid filter was non-existent
#Entity
#Table(name = "CATEGORY")
public class Category implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "CATEGORYID")
private int ID;
#Column(name = "CATEGORYNAME")
private String name;
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name = "CATEGORYID")
#OrderBy("TESTCASEID desc")
private Collection<TestCase> testCases;
...
}
#Entity
#Table(name = "TESTCASE_NEW")
#FilterDef(name = "TESTCASE_FILTER", parameters = { #ParamDef(name = "IDS", type = "int"), #ParamDef(name = "TESTCASE_NAME", type = "string") })
#Filters({ #Filter(name = "TEST_RUN_ID_FILTER", condition = "TESTRUNID in (:IDS)"), #Filter(name = "TESTCASE_NAME_FILTER", condition = "TESTCASENAME like :TESTCASE_NAME") })
// #FilterDef(name = "TEST_RUN_ID_FILTER", defaultCondition = "TESTRUNID in (:IDS)", parameters = { #ParamDef(name =
// "IDS", type = "int") })
public class TestCase implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "TESTCASEID")
private int ID;
#Column(name = "TESTCASENAME")
private String name;
...
}
#SuppressWarnings("unchecked")
public List<Category> getCategories(List<Integer> testRunIDs, String category, String testCaseName)
{
Session session = getSession();
session.enableFilter("FILE_TYPE_FILTER");
if (testRunIDs != null && testRunIDs.size() != 0)
{
session.enableFilter("TEST_RUN_ID_FILTER").setParameterList("IDS", testRunIDs);
}
if (category != null && !category.equals("0") && !category.equals(""))
{
session.enableFilter("CATEGORY_FILTER").setParameter("CATEGORY", category);
}
/*
* Hibernate wants to do an (left) outer join be default.
* This bit of HQL is required to get it to do an inner join.
* The query tells Hibernate to do an inner join on the testCases property inside the Category object
*/
Query query = session.createQuery("select distinct c from Category c inner join c.testCases tc");
List<Category> result = query.list();
return result;
..
}
Your help is greatly appreciated
I've solved it actually, but thanks for the help. The solution (detailed below) is to wrap multiple #FilterDef annotations in a #FilterDefs annotation. Oddly enough I didn't find this anywhere or in the Hibernate doc, I saw this post (Multiple annotations of the same type on one element?), and thought hey maybee #FilterDefs exists and it does.
#Entity
#Table(name = "TESTCASE_NEW")
#FilterDefs({
#FilterDef(name = "TESTCASE_NAME_FILTER", defaultCondition = "TESTCASENAME like :TESTCASENAME", parameters = { #ParamDef(name = "TESTCASENAME", type = "string") }),
#FilterDef(name = "TEST_RUN_ID_FILTER", defaultCondition = "TESTRUNID in (:IDS)", parameters = { #ParamDef(name = "IDS", type = "int") })
})
public class TestCase implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "TESTCASEID")
private int ID;
#Column(name = "TESTCASENAME")
private String name;
...
}
#Entity
public class Category implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "CATEGORYID")
private int ID;
#Column(name = "CATEGORYNAME")
private String name;
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name = "CATEGORYID")
#OrderBy("TESTCASEID desc")
#Filters({
#Filter(name = "TEST_RUN_ID_FILTER"),
#Filter(name = "TESTCASE_NAME_FILTER") })
private Collection<TestCase> testCases;
...
}
In the DAO, I just turn on the ones I need
public List<Category> getCategories(List<Integer> testRunIDs, String category, String testCaseName)
{
Session session = getSession();
if (testRunIDs != null && testRunIDs.size() != 0)
{
session.enableFilter("TEST_RUN_ID_FILTER").setParameterList("IDS", testRunIDs);
}
if (testCaseName != null)
{
session.enableFilter("TESTCASE_NAME_FILTER").setParameter("TESTCASENAME", testCaseName);
}
/*
* Hibernate wants to do an (left) outer join be default.
* This bit of HQL is required to get it to do an inner join.
* The query tells Hibernate to do an inner join on the testCases property inside the Category object
*/
Query query = session.createQuery("select distinct c from Category c inner join c.testCases tc");
List<Category> result = query.list();
return result;
}

Categories

Resources