Diffrence between _Id and Id in JPA - java

What's the difference between those two lines in JPA
public interface PostRepository extends JpaRepository<Post, Long> {
List<Post> findByUser_Id(Long id);
}
And
public interface PostRepository extends JpaRepository<Post, Long> {
List<Post> findByUserId(Long id);
}
So i edited my question to be more clearly and get a good response so there is my domain classes User and Post and i have relation #ManyToOne in Post class.
Domain
...
public class Post implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
And
...
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...

If you are using Spring Data JPA then class is a Spring JPA repository in which the implementation is done by the Spring Framework and the method name is used for construction of the query.
Check 2.3.2 Query creation for how the query will be constructed.
So, in your case List<Post> findByUser_Id(Long id); method might throw error on runtime since it's not in valid method format.

Its just the name of the method. Other than that, there is no difference between those lines.

Related

possible alternatives to #GeneratedValue with #EmbeddedId in JPA

My entity has a wrapped Identifier like this,
#Entity
public class Article {
#EmbeddedId
private ArticleId articleId;
....
}
#Embeddable
public class ArticleId implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
}
in my architecture, multiple application instances(it all same.) are connected to the same data source
so #GeneratedValue(strategy = GenerationType.IDENTITY)seems good
because even if instances A and B try to create Accountat the same time, Its Id is guaranteed by the database.
problem is that #GeneratedValue is only able to use with #Id annotation (#Id is not available for EmbeddedId)
PersistenceUnitUtil.getIdentifier(Object entity) could be a alternative? like this,
ArticleId articleId = ArticleRepository.nextIdentity();
I am not sure that whether it causes the race condition.
Could PersistenceUnitUtil.getIdentifier(Object entity) guarantee the unique id across the different application instance(JVM)? I don't think so.
In this situation, What alternative is possible?
One solution could be to use an #IdClass to get rid of the nested property and be able to generate the identifier (since nested properties are "assigned" and cannot be generated, so the call of PersistenceUnitUtil.getIdentifier(Object entity) would not help here). See e.g. here for a complete guide (also linked in the linked answer by #SternK from the comment)
An #IdClass could look like this:
public class ArticleId implements Serializable {
private Long id;
}
An entity could use it:
#Entity
#IdClass(ArticleId.class) // specified dependency
public class Article {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
// expose "typed" id:
public ArticleId getId() {
return new ArticleId(id);
}
}
Spring-Data #Repositorys also work with corresponding #IdClass objects, e.g.:
#Repository
public interface UserEntityRepository extends JpaRepository<Article, ArticleId> {
}
// would offer e.g. this method:
repository.findById(new ArticleId(123L));

How to create an api like this 'GET host:///api?user.username=bug' in Springboot?

I saw this kind of API style once and it worked proper
Noob here and I am current learning RESTful stuff,If anyone who may gives some advice and instruction.I'd be very appreciate!
Get URL
//The argument isn't mandatory, May be order.orderInfo,order.orderPrice etc
http://localhost:8080/order?order.orderNo=123
Controller code
#GetMapping
CollectionModel<Order> getOrders(Order order) {
List<Order> ordersResult = orderService.getOrders(order);
for (Order result : ordersResult) {
Link selfLink = WebMvcLinkBuilder.linkTo(OrderController.class).slash(result.getId()).withSelfRel();
result.add(selfLink);
}
Link link = WebMvcLinkBuilder.linkTo(OrderController.class).withSelfRel();
return CollectionModel.of(ordersResult, link);
}
Entity code
public class Order extends RepresentationModel<Order> implements Serializable {
#Id
#GeneratedValue
#Column(unique = true)
private Integer id;
private Long orderNo;
}
And my jpa repository
public interface OrderRepository extends JpaRepository<Order, Integer>,PagingAndSortingRepository<Order, Integer> {
}
I have finally figured out that this kind of URL is not work this way.
Shoud be apply to a specific situation.Which is the get endpoint method has a 'Relative Object'.Then we may use URL like this to improve flexable api.
Talk is cheap,I'll show you the code!
Entity->Customer
public class Customer extends RepresentationModel<Customer> implements Serializable {
#Id
#GeneratedValue
#Column(unique = true)
private Integer id;
private String name;
//Add relative Object to entity.
#OneToOne
private Order order;
}
Entity->Order
public class Order extends RepresentationModel<Order> implements Serializable {
#Id
#GeneratedValue
#Column(unique = true)
private Integer id;
private Long orderNo;
//Add relative Object to entity.
#OneToOne
private Customer customer;
}
Endpoint->CustomerController/getMethod
#GetMapping
CollectionModel<Customer> getCustomers(Customer customer) {
List<Customer> customersResult =
customerService.getCustomers(customer);
for (Customer result : customersResult) {
Link selfLink = WebMvcLinkBuilder.linkTo(CustomerController.class).slash(result.getId()).withSelfRel();
result.add(selfLink);
}
Link link = WebMvcLinkBuilder.linkTo(CustomerController.class).withSelfRel();
return CollectionModel.of(customersResult, link);
}
URL
scheme://[api]/[order.orderNo=123]
Then the value will mapping to paramter-custoemr inside.
PS:HTTP method '#fragment' may suitable for this case.
Thanks to #JRichardsz :)

Spring JPA repository doesn't return List of entities

I try to get simple List of Rawtype entities with help of findBy method in the myMethod. But I get nothing - rawtypes doesn't contain any entity. Although findAll method works fine. Please tell we where is my mistake.
Rawtype.java
#Entity
#Table(name="rawtype")
public class Rawtype implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="rtid", nullable = false)
#GeneratedValue
private int rtId;
#Column(name="rtname", nullable = false)
private String rtName;
//getters and setters
RawtypeRepository.java
public interface RawtypeRepository extends JpaRepository<Rawtype, Integer> {
List<Rawtype> findByRtName(String rtName);
}
RawtypeServiceImpl.java
#Service
#Transactional
public class RawtypeServiceImpl implements RawtypeService {
#Autowired
RawtypeRepository rawtypeRepository;
public List<Rawtype> findAll() {
return rawtypeRepository.findAll();
}
public myMethod(){
List<Rawtype> rawtypes = rawtypeRepository.findByRtName("RawName");
}
}
Can you try printing rtName of all the entities returned by findAll() method? May be there isn't any record with 'RawName' as rtName.
Also, you can enable logging for JPA to see the generated query.

Error when trying to map a recursive relation

I'm trying to map a recursive relation using JPA. I don't know why I'm getting some errors on the #OneToMany line.
Here is a code sample:
#Entity
public class RecursiveType implements Serializable {
private static final long serialVersionUID = -2459343636539882731L;
#Id
public int id;
#OneToMany(mappedBy="rec1", cascade=CascadeType.PERSIST) //here is where I get the errors
public RecursiveType rec1;
public Map<String, Map<RecursiveType, List<Map<RecursiveType, List<InnerTypes>>>>> rec2;
//getters and setters
}
And the line of persistence.xml file
<class>pt.ptinovacao.persistencetester.model.RecursiveType</class>
I've had several errors like: "Target entity is not defined" and "The attribute type for a collection mapping must be java.util.Collection…"
Why does this happen?
I've fixed it, I just changed the annotations and the relation type
#Entity
public class RecursiveType implements Serializable {
private static final long serialVersionUID = -2459343636539882731L;
#Id
public int id;
#OneToOne(cascade=CascadeType.ALL)
#JoinColumn(name="REC1_ID", referencedColumnName="ID")
public RecursiveType rec1;
public Map<String, Map<RecursiveType, List<Map<RecursiveType, List<InnerTypes>>>>> rec2; //I really don't need to try and map this xD
//getters and setters
}

How to call #NamedQueries from interface method definition?

I'm very new in Spring Framework, I want to know if is possible invoke Entity Named Query only defining the Named Query on the interface without any implementation.
I want to do something like this.
NamedQuery(name = "StateBo.findByCountry", query = "SELECT state FROM StateBo state WHERE state.country.id = ?")
#Table(name = "STATE")
#Entity(name = "StateBo")
public class StateBo extends BaseNamedBo {
private static final long serialVersionUID = 3687061742742506831L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "STATE_ID")
private Long id;
#Column(name = "ISO_CODE")
private String isoCode;
#ManyToOne
#JoinColumn(name = "COUNTRY_ID")
private CountryBo country;
// getters and setters ...
}
I defined the Named Query StateBo.findByBCountry, my interface looks like this
public interface IStateDao extends JpaRepository<StateBo, Long> {
public List<StateBo> findByCountry(Long id);
}
And the interface implementation looks like this.
#Transactional
#Repository("stateDao")
public class StateDao implements IStateDao {
}
But I have the error that I have to implement the methods that I'm defining on my interface, but I don't want to do that. I only want define my Named Query and define the method in my interface with the same name that is on the Entity and don't add the implementation of that method because the implementation is basically the String Named Query
You can use Spring Data Jpa project.
For start you see https://spring.io/guides/gs/accessing-data-jpa/
To execute query without an implementation(only interface) see http://docs.spring.io/spring-data/jpa/docs/1.6.0.RELEASE/reference/htmlsingle/#jpa.query-methods.at-query
Basically you don't need the implementation:
#Transactional
#Repository("stateDao")
public class StateDao implements IStateDao {
}
try to remove that and see what will happen.

Categories