SequenceGenerator not using next value of databasesequence - oracle

I have a problem in my application. I have an Oracle database with a sequence on a table. When i view the sequence in the database it says that last_number is 33800. However, when I try inserting a new object from my application the generated id is not 33800, but rather a smaller number. My guess is that Hibernate or whatever just finds the next available number. It does happen that my application deletes rows in the table, thus causing holes in the id-sequence. So, eventually I will get an exception because an ID i am trying to insert has already been used.
How can I configure the application so that it is always the sequence's last number + 1 that is used? I thought that this was default behavior, as I cannot recall encountering this problem.
This is my entity:
#Entity
#SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "MY_SEQ", allocationSize = 20)
#Table(name = "myEntity")
public class myEntity {
private Long id;
#Id
#Column(name = "id")
#GeneratedValue(generator = "SequenceIdGenerator")
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
}

you can let hibernate handle this by
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id", nullable = false)
private Long id;
you can read more about it here https://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing
You are using ORACLE so for you GenerationType.SEQUENCE will work as GenerationType.IDENTITY is not supported by Oracle

Related

Make hibernate continue the sequence from a previous database for id generation values

I have this entity:
#Entity
#Table(name = "street_type")
public class StreetType {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "type")
private String type;
#OneToMany(mappedBy = "streetType")
private Set<TransitRoute> transitRoutes;
Which i want to has the id auto-incremented, the problem is that in the database i have already some data, so the last row it has an id of 5, so how i make Hibernate to start the auto-increment value to start with 5 and continue with the given strategy.
I found the GenericGenerator decorator but i do not found a good example of how to use it. I already see this post but i got the same error of ERROR: relation "hibernate_sequence" does not exist

Troubles with Bidirectional One-To-One JPA

I'm coding a CRUD JPA web application. My goal is that a given parent Vehicle can only have a single child Driver, but during runtime this same Driver can instead be assigned to another Vehicle and vice versa. To my understanding, this could be accomplished via an OneToOne relationship.
I've tried some different approaches, but to no success. I can assign a Vehicle to a Driver just fine, but when I try to update/create a new Vehicle and give him a Driver, via controllers, nothing happens. I can only do it the other way around. I'm assuming this is because Vehicle is the parent and I can only create a new relation by updating a parent.
My question is, is it possible to make these updates bidirectional and how can I achieve that?
I've tried using a shared primary key, using a foreign key, using a join table. The result is always the same and I can't quite grasp why. I have an OneToMany relationship working on this application and it works as I expect it to work. I can update on one side or the other, delete on one side or the other. Both entities have been updated. OneToOne? Parent seems to have all the power.
This is what I'm working with right now:
Driver
#Entity
#Table(name= "drivers")
public class Driver {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String name;
#Column(nullable = false)
private int age;
#OneToOne(mappedBy = "driver")
private Vehicle vehicle;
Vehicle
#Entity
#Table(name= "vehicles")
public class Vehicle {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String make;
#Column(nullable = false)
private String model;
#Column(nullable = false)
private int mileage;
#Column(nullable = false)
private int year;
#Column(nullable = false)
private int fuel;
#OneToOne
#JoinColumn(name = "driver_id")
private Driver driver;
And just for reference, this is the OneToMany relationship I have and that I'm happy with. I'd like my OneToOne to have the same behavior, except I don't need to save a list of entities, only one.
#Entity
#Table(name="stops")
public class Stop {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String name;
#ManyToOne
#JoinColumn(name="route_id")
private Route route;
#Entity
#Table(name="routes")
public class Route {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String name;
#OneToMany
#JoinColumn(name = "route_id")
private List<Stop> stops = new ArrayList<>();
Any tips would be appreciated, thank you for your time.

Spring Boot JPA - OneToMany relationship and database structure

I wonder what database structure would be the best option in my case:
I have entity Questionnaire:
#Table(name = "questionnaire")
public class Questionnaire extends BaseEntity {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToMany(mappedBy = "fieldStatus")
private List<QuestionnaireField > fieldStatusList;
}
#Table(name = "questionnaire_field")
public class QuestionnaireField extends BaseEntity {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "questionnaire_id")
private Long questionnaireId;
#Column(name = "field_id")
private Long fieldId; //this is id related to the other table Field
#Column(name = "completed")
private boolean completed; //because I need some additional informations like completed I think I can't use ManyToMany between Questionnaire and Field
#ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
#JoinColumn(name = "questionnaire_id")
private Questionnaire questionnaire;
As you see each Questionnaire can have multiple QuestionnaireFields, BUT each QuestionnaireField is of type Field (hence I added private Long fieldId). Table Field can have 10.000 different fields.
Summary:
one questionnaire can have e.g. 10 Fields, the second one 20 another Fields etc. To store fields related to some particular Questionnaire I created QuestionnaireField table with 2 columns: private Long questionnaireId; and private Long fieldId; . The question is if it is a good approach? That are plain columns not related to any Foreign Key... I try to find the best solution to save Questionnaire with related QuestionnaireFields that are a subset of a big Field table...

Spring Data lock table to read while writing

I am using Spring data in my app (2.0.1). The app is REST-based service which add orders.
The order entity looks as follows:
#Entity
#Table(name = "orders")
#Data
#NoArgsConstructor
public class OrderEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Version
private int version;
private Date date;
private String post;
private BigDecimal totalAmount;
#Enumerated(EnumType.STRING)
private OrderStatus status;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "order_id")
List<OrderSetEntity> sets;
private int dailyNumber;
private String documentNumber;
The posting or orders happens in OrderService:
public Long postOrder(OrderDTO orderDTO){
Date date = new Date();
OrderEntity order = new OrderEntity(date, orderDTO.getPost(), orderDTO.getPaymentMethod());
Integer dailyNumber = orderRepository.findDailyNumberByDate(date) + 1;
order.setDailyNumber(dailyNumber);
orderRepository.save(order);
return order.getId();
}
while findDailyNumberByDate is implemented this way:
#Override
public int findDailyNumberByDate(Date date) {
String sql = String.format("select max(o.dailyNumber) from OrderEntity o ");
Query query = entityManager.createQuery(sql);
Integer result = (Integer) query.getSingleResult();
if (result == null){
return 0;
}else {
return result.intValue();
}
Now I have a problem, that it get duplicated dailyNumber. The table isn't locked for reading when I am about to write into it.
How can I achieve it?
I tried lockin the table - #Lock(LockModeType.PESSIMISTIC_WRITE)
or query.setLockMode(LockModeType.PESSIMISTIC_FORCE_INCREMENT);
but is still isn't working.
Thanks a lot for help
LockModeType can work in different ways with different databases, especially with Oracle db it gets a little tricky. A similar issue was answered here jpa lockmode type npt working as expected

EntityNotFoundException in Hibernate Many To One mapping however data exist

I'm getting an error
Caused by: javax.persistence.EntityNotFoundException: Unable to find tn.entities.AgenceBnq with id 01
when I get AgenceBnq through Employee
Employee class:
#Table(name = "EMPLOYEE")
#NamedQuery(name = "Employee.findById", query = "SELECT e FROM Employee e WHERE e.employeMat = ?1"),
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "EMPLOYEE_MAT", unique = true, nullable = false, length = 15)
private String employeeMat;
...
#ManyToOne
#JoinColumn(name = "AGENCE_COD")
private AgenceBnq agenceBnq;
}
#Entity
#Table(name="AGENCEBNQ")
public class AgenceBnq implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="AGENCE_COD", unique=true, nullable=false, length=10)
private String agenceCod;
...
//bi-directional many-to-one association to Employee
#OneToMany(mappedBy="agenceBnq")
private Set<Employee> employees;
}
I'm calling namedQuery Employee.findById in DAO to retrieve data and I have to get AgenceBnq from Employee but get this error while calling query.getResultList()
#NotFound( action = NotFoundAction.IGNORE) isn't useful for me because data exist in AGENCEBNQ table and I have to retrieve date through Employee.
Is this a bug in hibernate ? I'm using hibernate version 3.6.7.Final
Firstly, You dont need query for it, the EnityManger.find(Employee.class, YOUR_ID) will do the job.
Secondly dont use ? in your queries but names (e.employeMat = :id) as it is easier to debug and less error prones for complicated queries.
Finally, check your DB table if the AGENCE_COD column in Employee table really contains the valid ID for your entitity that crashes (and that it length matches the ID length of AgenceBnq). It should work, the typical reason why it doesnt will be that your Employe.AGENCE_COD has defualt value and when creatubg the new EMploye you add it only to the Agence but you did not set Agence in the Employ.

Resources