I have a java method with insert and select like that:
#Override
public Page<ApprovalProcessEntity> getApprovalProcess(int page, int size, String approvalNum, String approvalType, int approvalStatus, Date start, Date end) {
//jpa inseart
checkAndInsertApprovalProcess();
//querydsl select
return getApprovalProcess2(page, size, approvalNum, approvalType, approvalStatus, start, end);
}
#Override
#Transactional(rollbackFor = Exception.class)
public void checkAndInsertApprovalProcess() {
List<Task> list = taskService.createTaskQuery().taskCandidateOrAssigned(curUserId()).list();
String confirmVar = "IS_CONFIRM";
List<ApprovalProcessEntity> entities = new ArrayList<>();
Set<String> processInstanceIds = new HashSet<>();
for (Task task : list) {
processInstanceIds.add(task.getProcessInstanceId());
}
Map<String, ApprovalApplyEntity> map = approvalApplyDao.findAllByProcessInstanceIdIn(processInstanceIds).stream().collect(Collectors.toMap(ApprovalApplyEntity::getProcessInstanceId, k -> k));
for (Task task : list) {
Object confirm = taskService.getVariable(task.getId(), confirmVar);
if (confirm != null) {
continue;
}
taskService.setVariable(task.getId(), confirmVar, true);
ApprovalProcessEntity entity = new ApprovalProcessEntity();
String processInstanceId = task.getProcessInstanceId();
ApprovalApplyEntity apply = map.get(processInstanceId);
entity.setApprovalStatus(1);
entity.setCurNode(task.getName());
entities.add(entity);
}
approvalProcessDao.saveAll(entities);
}
Page<ApprovalProcessEntity> getApprovalProcess2(int page, int size, String approvalNum, String approvalType, int approvalStatus, Date start, Date end) {
String userId = curUserId();
QApprovalProcessEntity qEntity = QApprovalProcessEntity.approvalProcessEntity;
JPAQuery<ApprovalProcessEntity> jpaQuery = queryFactory
.selectFrom(qEntity)
.where(qEntity.createTime.between(start, end))
.where(qEntity.createPerson.eq(userId));
if (StrUtil.isNotBlank(approvalNum)) {
jpaQuery = jpaQuery.where(qEntity.approvalNum.eq(approvalNum));
}
if (StrUtil.isNotBlank(approvalType)) {
jpaQuery = jpaQuery.where(qEntity.approvalType.eq(approvalType));
}
if (approvalStatus != -1) {
jpaQuery = jpaQuery.where(qEntity.approvalStatus.eq(approvalStatus));
}
PageRequest pr = PageRequest.of(page, size);
List<ApprovalProcessEntity> entities = jpaQuery.offset(pr.getOffset()).limit(pr.getPageSize()).fetch();
return new PageImpl<>(entities, pr, jpaQuery.fetchCount());
}
if some task haven't be confirmed,insert a new entity in to table;
then select data from this table;
if I use the following code,
when I had a new task, it can insert successfully,
but can't select data immediately,
if call getApprovalProcess() again, getApprovalProcess2() method work well,
so how can I select data immediately after insert;
meanwhile, if i change getApprovalProcess2() likeļ¼
Page<ApprovalProcessEntity> getApprovalProcess2(int page, int size, String approvalNum, String approvalType, int approvalStatus, Date start, Date end) {
return approvalProcessDao.findAll(PageRequest.of(page, size));
}
then create a new task and call getApprovalProcess() method again()
it can select data immediately, work well
but actually what I want is Previous Impl,so what should I do that can make it work;
Related
I m trying to implement a Paginated TableView that allows sorting by all items in JavaFX. I implemented the paginated tableview from here: https://stackoverflow.com/a/25424208/12181863. provided by jewelsea and tim buthe.
I was thinking that because the table view is only accessing a sublist of items, i wanted to extend the sorting from the table columns to the full list based on what i understand on the section about sorting on the Java Docs: https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TableView.html#setItems-javafx.collections.ObservableList-
// bind the sortedList comparator to the TableView comparator
//i m guessing it extends the sorting from the table to the actual list?
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
and then refresh the tableview for the same sublist indexes (which should now be sorted since the whole list is sorted).
Basically, I want to use the table column comparator to sort the full list, and then "refresh" the tableview using the new sorted list. Is this feasible? Or is there a simpler way to go about this?
I also referred to other reference material such as : https://incepttechnologies.blogspot.com/p/javafx-tableview-with-pagination-and.html but i found it hard to understand since everything was all over the place with vague explanation.
A quick extract of the core components in my TouchDisplayEmulatorController class
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Pagination;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;
import java.util.ArrayList;
import java.util.List;
public class TouchDisplayEmulatorController extends Application {
public TableView sensorsTable;
public List<Sensor> sensors;
public int rowsPerPage = 14;
public GridPane grids = new GridPane();
public long timenow;
public void start(final Stage stage) throws Exception {
grids = new GridPane();
setGridPane();
Scene scene = new Scene(grids, 1024, 768);
stage.setScene(scene);
stage.setTitle("Table pager");
stage.show();
}
//public static void main(String[] args) throws Exception {
// launch(args);
//}
public void setGridPane(){
processSensors();
sensorsGrid();
}
public void sensorsGrid(){
buildTable();
int numOfPages = 1;
if (sensors.size() % rowsPerPage == 0) {
numOfPages = sensors.size() / rowsPerPage;
} else if (sensors.size() > rowsPerPage) {
numOfPages = sensors.size() / rowsPerPage + 1;
}
Pagination pagination = new Pagination((numOfPages), 0);
pagination.setPageFactory(this::createPage);
pagination.setMaxPageIndicatorCount(numOfPages);
grids.add(pagination, 0, 0);
}
private Node createPage(int pageIndex) {
int fromIndex = pageIndex * rowsPerPage;
int toIndex = Math.min(fromIndex + rowsPerPage, sensors.size());
sensorsTable.setItems(FXCollections.observableArrayList(sensors.subList(fromIndex, toIndex)));
return new BorderPane(sensorsTable);
}
public void processSensors(){
sensors = new ArrayList<>();
// long timenow = OffsetDateTime.now(ZoneOffset.UTC).toInstant().toEpochMilli()/1000;
// StringTokenizer hildetoken = new StringTokenizer(msg);
for (int i=0; i<20; i++) {
sensors.add(new Sensor(String.valueOf(i), "rid-"+i, "sid-"+i, "0", "0", "no condition"));
}
}
public void buildTable() {
sensorsTable = new TableView();
TableColumn<Sensor, String> userid = new TableColumn<>("userid");
userid.setCellValueFactory(param -> param.getValue().userid);
userid.setPrefWidth(100);
TableColumn<Sensor, String> resourceid = new TableColumn<>("resourceid");
resourceid.setCellValueFactory(param -> param.getValue().resourceid);
resourceid.setPrefWidth(100);
TableColumn<Sensor, String> column1 = new TableColumn<>("sid");
column1.setCellValueFactory(param -> param.getValue().sid);
column1.setPrefWidth(100);
TableColumn<Sensor, String> column2 = new TableColumn<>("timestamp");
column2.setCellValueFactory(param -> param.getValue().timestamp);
column2.setPrefWidth(100);
TableColumn<Sensor, String> column3 = new TableColumn<>("reading");
column3.setCellValueFactory(param -> param.getValue().reading);
column3.setPrefWidth(100);
TableColumn<Sensor, String> column4 = new TableColumn<>("last contacted");
column4.setCellFactory(new Callback<TableColumn<Sensor, String>, TableCell<Sensor, String>>() {
#Override
public TableCell<Sensor, String> call(TableColumn<Sensor, String> sensorStringTableColumn) {
return new TableCell<Sensor, String>() {
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!isEmpty()) {
this.setTextFill(Color.WHITE);
if (item.contains("#")) {
this.setTextFill(Color.BLUEVIOLET);
} else if (item.equals("> 8 hour ago")) {
this.setStyle("-fx-background-color: red;");
} else if (item.equals("< 8 hour ago")) {
this.setStyle("-fx-background-color: orange;");
//this.setTextFill(Color.ORANGE);
} else if (item.equals("< 4 hour ago")) {
this.setStyle("-fx-background-color: yellow;");
this.setTextFill(Color.BLACK);
} else if (item.equals("< 1 hour ago")) {
this.setStyle("-fx-background-color: green;");
//this.setTextFill(Color.GREEN);
}
setText(item);
}
}
};
}
});
column4.setCellValueFactory(param -> param.getValue().condition);
column4.setPrefWidth(100);
sensorsTable.getColumns().addAll(userid, resourceid, column1, column2, column3, column4);
}
}
class Sensor {
public SimpleStringProperty userid;
public SimpleStringProperty resourceid;
public SimpleStringProperty sid;
public SimpleStringProperty timestamp;
public SimpleStringProperty reading;
public SimpleStringProperty condition;
public Sensor(String userid, String resourceid, String sid, String timestamp, String reading, String condition){
this.userid = new SimpleStringProperty(userid);
this.resourceid = new SimpleStringProperty(resourceid);
this.sid = new SimpleStringProperty(sid);
this.timestamp = new SimpleStringProperty(timestamp);
this.reading = new SimpleStringProperty(reading);
this.condition = new SimpleStringProperty(condition);
//we can use empty string or condition 3 here
}
public Sensor(String sid, String timestamp, String reading, String condition){
this.userid = new SimpleStringProperty("-1");
this.resourceid = new SimpleStringProperty("-1");
this.sid = new SimpleStringProperty(sid);
this.timestamp= new SimpleStringProperty(timestamp);
this.reading= new SimpleStringProperty(reading);
this.condition = new SimpleStringProperty(condition);
}
public String getUserid() { return this.userid.toString(); }
public String getResourceid() { return this.resourceid.toString(); }
public String getSid() { return this.sid.toString(); }
public String getTimestamp() { return this.timestamp.toString(); }
public String getReading() { return this.reading.toString(); }
public String getCondition() { return this.condition.toString(); }
public String toString() { return "userid: "+getUserid()+" resourceid: "+getResourceid()+" sid: "+getSid()+
"\ntimestamp: "+getTimestamp()+" reading: "+getReading()+" condition: "+getCondition();}
}
separate class:
public class tester {
public static void main(String[] args) {
Application.launch(TouchDisplayEmulatorController.class, args);
}
}
Pagination of a TableView is not directly supported, so we have to do it ourselves. Note that the solutions referenced in the question pre-date the (re-introduction of Sorted-/FilteredList)
Nowadays, the basic approach is to use a FilteredList that contains only the rows which are on the current page. This filteredList must be the value of the table's itemsProperty. To also allow sorting, we need to wrap the original data into a SortedList and bind its comparator to the comparator provided by the table. Combining all:
items = observableArrayList(... //my data);
sortedList = new SortedList(items);
filteredList = new FilteredList(sortedList);
table.setItems(filteredList);
sortedList.comparatorProperty().bind(table.comparatorProperty());
Looks good, doesn't it? Unfortunately, nothing happens when clicking onto a column header. The reason:
the collaborator that's responsible for the sort is the sortPolicy
the default policy checks whether the table's items is a sorted list: if so (and its comparator is bound to the table's), sorting is left to that list, otherwise it falls back to FXCollections.sort(items, ...)
collections.sort fails to do anything because a filtered list is unmodifiable
In pseudo code:
if (items instanceof SortedList) {
return sortedList.getComparator().isBoundTo(table.getComparator());
}
try {
FXCollections.sort(items);
// sorting succeeded
return true;
} catch (Exception ex) {
// sorting failed
return false;
}
The way out is to implement a custom sort policy: instead of only checking the table's items for being a sortedList, it walks up the chain of transformationList (if available) sources until it finds a sorted (or not):
ObservableList<?> lookup = items;
while (lookup instanceof TransformationList) {
if (lookup instanceof SortedList) {
items = lookup;
break;
} else {
lookup = ((TransformationList<?, ?>) lookup).getSource();
}
}
// ... same as original policy
Now we have the sorting (of the complete list) ready - next question is what should happen to the paged view after sorting. Options:
keep the page constant and updated the filter
keep any of the current items visible and update the page
Both require to trigger the update when the sort state of the list changes, which to implement depends on UX guidelines.
A runnable example:
public class TableWithPaginationSO extends Application {
public static <T> Callback<TableView<T>, Boolean> createSortPolicy(TableView<T> table) {
// c&p of DEFAULT_SORT_POLICY except adding search up a chain
// of transformation lists until we find a sortedList
return new Callback<TableView<T>, Boolean>() {
#Override
public Boolean call(TableView<T> table) {
try {
ObservableList<?> itemsList = table.getItems();
// walk up the source lists to find the first sorted
ObservableList<?> lookup = itemsList;
while (lookup instanceof TransformationList) {
if (lookup instanceof SortedList) {
itemsList = lookup;
break;
} else {
lookup = ((TransformationList<?, ?>) lookup).getSource();
}
}
if (itemsList instanceof SortedList) {
SortedList<?> sortedList = (SortedList<?>) itemsList;
boolean comparatorsBound = sortedList.comparatorProperty()
.isEqualTo(table.comparatorProperty()).get();
return comparatorsBound;
} else {
if (itemsList == null || itemsList.isEmpty()) {
// sorting is not supported on null or empty lists
return true;
}
Comparator comparator = table.getComparator();
if (comparator == null) {
return true;
}
// otherwise we attempt to do a manual sort, and if successful
// we return true
FXCollections.sort(itemsList, comparator);
return true;
}
} catch (UnsupportedOperationException e) {
return false;
}
};
};
}
private Parent createContent() {
initData();
// wrap sorted list around data
sorted = new SortedList<>(data);
// wrap filtered list around sorted
filtered = new FilteredList<>(sorted);
// use filtered as table's items
table = new TableView<>(filtered);
addColumns();
page = new BorderPane(table);
// install custom sort policy
table.setSortPolicy(createSortPolicy(table));
// bind sorted comparator to table's
sorted.comparatorProperty().bind(table.comparatorProperty());
pagination = new Pagination(rowsPerPage, 0);
pagination.setPageCount(sorted.size() / rowsPerPage);;
pagination.setPageFactory(this::createPage);
sorted.addListener((ListChangeListener<Locale>) c -> {
// update page after changes to list
updatePage(true);
});
return pagination;
}
private Node createPage(int pageIndex) {
updatePredicate(pageIndex);
return page;
}
/**
* Update the filter to show the current page.
*/
private void updatePredicate(int pageIndex) {
int first = rowsPerPage * pageIndex;
int last = Math.min(first + rowsPerPage, sorted.size());
Predicate<Locale> predicate = loc -> {
int index = sorted.indexOf(loc);
return index >= first && index < last;
};
filtered.setPredicate(predicate);
// keep reference to first on page
firstOnPage = filtered.get(0);
}
/**
* Update the page after changes to the list.
*/
private void updatePage(boolean keepItemVisible) {
if (keepItemVisible) {
int sortedIndex = sorted.indexOf(firstOnPage);
int pageIndex = sortedIndex >= 0 ? sortedIndex / rowsPerPage : 0;
pagination.setCurrentPageIndex(pageIndex);
} else {
updatePredicate(pagination.getCurrentPageIndex());
}
}
private void addColumns() {
TableColumn<Locale, String> name = new TableColumn<>("Name");
name.setCellValueFactory(new PropertyValueFactory<>("displayName"));
TableColumn<Locale, String> country = new TableColumn<>("Country");
country.setCellValueFactory(new PropertyValueFactory<>("displayCountry"));
table.getColumns().addAll(name, country);
}
private void initData() {
Locale[] availableLocales = Locale.getAvailableLocales();
data = observableArrayList(
Arrays.stream(availableLocales)
.filter(e -> e.getDisplayName().length() > 0)
.limit(120)
.collect(toList())
);
}
private TableView<Locale> table;
private Pagination pagination;
private BorderPane page;
private ObservableList<Locale> data;
private FilteredList<Locale> filtered;
private SortedList<Locale> sorted;
private Locale firstOnPage;
private int rowsPerPage = 15;
#Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
First off, it's not clear that Pagination is the correct control for this, although the UI for page selection is really nice. Your problems might stem from the fact that you're putting the TableView into a new BorderPane each time, or it might come from the fact that you're using TableView.setItems().
An approach that works is to use FilteredList to handle the pagination, and just keep the TableView as a static element in the layout, not in the dynamic graphic area of the Pagination. To satisfy the need to have the Pagination do something, a Text with the page number was created.
A new property was added to Sensor - ordinalNumber. This is used to control the filter for the paging. The filter will dynamically change to select only those Sensor's with an ordinalNumber in a particular range. The range is controlled by the Pagination's currentPageIndexProperty. There's a listener on that property that regenerates the FilteredList's predicate property each time the page is changed.
That handles the page changes, but what about sorting the whole list? First, the FilteredList is wrapped in a SortedList, and it's the SortedList that's set into the TableView. The SortedList's Comparator is bound to the TableView's Comparator.
But the SortedList only sees the Sensors included under the current filter. So a listener was added to the TableView's comparatorProperty. The action for this listener Streams the underlying ObservableList, sorts it using the new Comparator, and resets each Sensor's ordinalNumber according to the new sort order.
Finally, in order to have the FilteredList re-evaluate the ObservableList, these ordinalNumber changes need to trigger a ListChange event. So an extractor was added to the ObservableList based on the ordinalNumber.
The result works pretty well, except for the goofy page numbering Text sliding onto the screen with each page change.
The entire code was cleaned up for readability and unused stuff was stripped out to keep the example minimal.
Here's the Sensor class:
class Sensor {
public SimpleStringProperty userid;
public SimpleStringProperty resourceid;
public SimpleStringProperty sid;
public SimpleStringProperty timestamp;
public SimpleStringProperty reading;
public IntegerProperty ordinalNumber = new SimpleIntegerProperty(0);
public Sensor(int userid, String resourceid, String sid, String timestamp, String reading, String condition) {
this.userid = new SimpleStringProperty(Integer.toString(userid));
this.resourceid = new SimpleStringProperty(resourceid);
this.sid = new SimpleStringProperty(sid);
this.timestamp = new SimpleStringProperty(timestamp);
this.reading = new SimpleStringProperty(reading);
this.ordinalNumber.set(userid);
}
}
Here's the layout code:
public class PaginationController extends Application {
public TableView<Sensor> sensorsTable = new TableView<>();
public ObservableList<Sensor> sensorObservableList = FXCollections.observableArrayList(sensor -> new Observable[]{sensor.ordinalNumber});
public FilteredList<Sensor> sensorFilteredList = new FilteredList<>(sensorObservableList);
public SortedList<Sensor> sensorSortedList = new SortedList<>(sensorFilteredList);
public IntegerProperty currentPage = new SimpleIntegerProperty(0);
public int rowsPerPage = 14;
public void start(final Stage stage) throws Exception {
processSensors();
stage.setScene(new Scene(buildScene(), 1024, 768));
stage.setTitle("Table pager");
stage.show();
}
public Region buildScene() {
buildTable();
int numOfPages = calculateNumOfPages();
Pagination pagination = new Pagination((numOfPages), 0);
pagination.setPageFactory(pageIndex -> {
Text text = new Text("This is page " + (pageIndex + 1));
return text;
});
pagination.setMaxPageIndicatorCount(numOfPages);
currentPage.bind(pagination.currentPageIndexProperty());
sensorFilteredList.predicateProperty().bind(Bindings.createObjectBinding(() -> createPageFilter(pagination.getCurrentPageIndex()), pagination.currentPageIndexProperty()));
return new VBox(sensorsTable, pagination);
}
#NotNull
private Predicate<Sensor> createPageFilter(int currentPage) {
int lowerLimit = (currentPage) * rowsPerPage;
int upperLimit = (currentPage + 1) * rowsPerPage;
return sensor -> (sensor.ordinalNumber.get() >= lowerLimit) &&
(sensor.ordinalNumber.get() < upperLimit);
}
private int calculateNumOfPages() {
int numOfPages = 1;
if (sensorObservableList.size() % rowsPerPage == 0) {
numOfPages = sensorObservableList.size() / rowsPerPage;
} else if (sensorObservableList.size() > rowsPerPage) {
numOfPages = sensorObservableList.size() / rowsPerPage + 1;
}
return numOfPages;
}
public void processSensors() {
Random random = new Random();
for (int i = 0; i < 60; i++) {
sensorObservableList.add(new Sensor(i, "rid-" + i, "sid-" + i, Integer.toString(random.nextInt(100)), "0", "no condition"));
}
}
public void buildTable() {
addStringColumn("userid", param1 -> param1.getValue().userid);
addStringColumn("resourceid", param1 -> param1.getValue().resourceid);
addStringColumn("sid", param1 -> param1.getValue().sid);
addStringColumn("timestamp", param1 -> param1.getValue().timestamp);
addStringColumn("reading", param1 -> param1.getValue().reading);
TableColumn<Sensor, Number> ordinalCol = new TableColumn<>("ordinal");
ordinalCol.setCellValueFactory(param -> param.getValue().ordinalNumber);
ordinalCol.setPrefWidth(100);
sensorsTable.getColumns().add(ordinalCol);
sensorsTable.setItems(sensorSortedList);
sensorSortedList.comparatorProperty().bind(sensorsTable.comparatorProperty());
sensorSortedList.comparatorProperty().addListener(x -> renumberRecords());
}
private void renumberRecords() {
AtomicInteger counter = new AtomicInteger(0);
Comparator<Sensor> newValue = sensorsTable.getComparator();
if (newValue != null) {
sensorObservableList.stream().sorted(newValue).forEach(sensor -> sensor.ordinalNumber.set(counter.getAndIncrement()));
} else {
sensorObservableList.forEach(sensor -> sensor.ordinalNumber.set(counter.getAndIncrement()));
}
}
#NotNull
private void addStringColumn(String columnTitle, Callback<TableColumn.CellDataFeatures<Sensor, String>, ObservableValue<String>> callback) {
TableColumn<Sensor, String> column = new TableColumn<>(columnTitle);
column.setCellValueFactory(callback);
column.setPrefWidth(100);
sensorsTable.getColumns().add(column);
}
}
For demonstration purposes, the timestamp field in the Sensor was initialized to a random number so that it would give an obvious change when that column was sorted. Also, the ordinalNumber field was added to the table so that it could be easily verified that they had been re-evaluated when a new sort column was chosen.
I have a database table in which there are already stored some data.
Now I want to have a Vaadin editable Table in my page with the data taken from database and when this Vaadin Table is updated (either add a row or edit the existing ones), the database should be updated aswell.
I was so close to that, but I realized I can't use just an INSERT query because the unique ID constraint is violated.
What can I do in order to achieve that? I really need your help!
The BeanItemContainer:
public BeanItemContainer createContainer() {
BeanItemContainer<Sct> beans = new BeanItemContainer<Sct>(Sct.class);
beans.addNestedContainerProperty("secti.sid");
beans.addNestedContainerProperty("secti.isa");
beans.addNestedContainerProperty("secti.order");
for (int i = 0; i < list.size(); i++) {
PS_SECTION section = list.get(i);
Long ps = section.getPS_SECTION();
String na = section.getNAME();
Long is = section.getISACTIVE();
Long or = section.getVORDER();
Object itemId = beans.addBean(new Sct(na, new BeanSect(ps, is, or)));
}
return beans;
}
Here is the save (update) button when clicked:
ClickListener saveListener = new ClickListener() {
private Long s4 = 0L;
#Override
public void buttonClick(ClickEvent event) {
Collection<?> itemIds = table.getItemIds();
Item item = null;
boolean isSaved = false;
PS_SECTION ps = null;
List<PS_SECTION> newlist = new ArrayList<PS_SECTION>();
int i = 0;
for(Object itemId : itemIds){
ps = new PS_SECTION();
item = table.getItem(itemId);
Long s1 = (Long) item.getItemProperty("ID").getValue();
String s2 = item.getItemProperty("SECTION").getValue().toString();
Long s3 = (Long) item.getItemProperty("ORDER").getValue();
Long s5 = 0L;
ps.setPS_SECTION(s1);
ps.setNAME(s2);
ps.setVORDER(s3);
ps.setISACTIVE(s4);
ps.setISGLOBAL(s5);
newlist.add(ps);
}
try {
// Here I call the query.
isSaved = dao.insertPsSections(newlist);
if (isSaved){
Notification.show("Success ");
unsavedChanges = false;
}
else if (!isSaved){
Notification.show("Problem");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Finally, the query:
public boolean insertPsSections(List<PS_SECTION> pssec) throws SQLException {
Boolean sv = false;
try {
this.setKeepConnOpen(true);
String insertsections = "INSERT INTO PS_SECTION"
+ "(PS_SECTION,NAME,ISACTIVE,ISGLOBAL,VORDER)"
+ "VALUES (?,?,?,?,?)";
for (PS_SECTION j : pssec){
Long section = j.getPS_SECTION();
String name = j.getNAME();
Long isa = j.getISACTIVE();
Long isg = j.getISGLOBAL();
Long order = j.getVORDER();
this.simpleUpdate(insertsections, false, section, name, isa, isg, order);
}
} finally {
this.doCommit();
this.closeConn(true);
sv=true;
}
return sv;
}
Hello am trying to fetch 10 rows of data from Cassandra table. But on each request same 10 row is returning. Please see my logic here. and advise me where am doing wrong here-
public class CustomerRequestDaoImpl implements CustomerRequestDao
{
private static Cluster cluster;
#Resource
private CassandraSessionFactory cassandraSessionFactory;
/** The ProductsByTagDaoImpl session. */
private Session session;
#Override
public List<CustomerRequest> getCustomerRequestData(final String productId, final String receiptPeriod)
{
final int RESULTS_PER_PAGE = 10;
session = cassandraSessionFactory.getSession();
final List<CustomerRequest> customerRequestdata = new ArrayList<CustomerRequest>();
try
{
final PreparedStatement statement =
session.prepare("select * from customer_request where product_id = :id and receipt_period = :receiptPeriod");
final BoundStatement boundStatement = new BoundStatement(statement);
boundStatement.setFetchSize(RESULTS_PER_PAGE);
boundStatement.setString("id", productId);
boundStatement.setString("receiptPeriod", receiptPeriod);
final ResultSet resultSet = session.execute(boundStatement);
final Iterator<Row> iter = resultSet.iterator();
final PagingState nextPage = resultSet.getExecutionInfo().getPagingState();
int remaining = resultSet.getAvailableWithoutFetching();
for (final Row rowdt : resultSet)
{
customerRequestdata.add(constructCustomerReq(rowdt));
if (--remaining == 0)
{
break;
}
}
}
catch (final Exception e)
{
e.printStackTrace();
}
return customerRequestdata;
}
#PostConstruct
public void init()
{
session = cassandraSessionFactory.getSession();
cluster = session.getCluster();
}
}
My Table-
My Table structure:-
CREATE TABLE customer_request (
product_id varchar PRIMARY KEY,
id varchar,
receipt_period varchar,
delivery_method_status varchar,
first_name varchar
);
return Response-
<e>
<deliveryMethodStatus null="true"/>
<firstName null="true"/>
<id>0b0352f6b3904</id>
<lastName Adkin="true"/>
<orderId>FORMS8a04e</orderId>
<orderItemId>FORMS8a04e-1</orderItemId>
<productId>PI_NAME_CHANGE</productId>
<receiptPeriod>2016-02-06</receiptPeriod>
<receivedDate null="true"/>
<requestData null="true"/>
Several remarks:
You should not re-prepare the query each time, it's an
anti-pattern. Prepare the statement only once and re-use it for each method call
The source code you show will always return the first page of
data because you break out of the for loop once remaining
variable counts down to 0. The PagingState object is not used
anywhere ...
You question is not clear either Hello am trying to fetch 10 rows of
data from Cassandra table. But on each request same 10 row is
returning. Which 10 rows do you want ? The first 10 rows ? The
10 rows after a threshold ?
Sample code for paging:
Note: prepared the following query only once: select * from customer_request where product_id = :id and receipt_period = :receiptPeriod LIMIT :lim and pass it along with the method
#Override
public List<Tuple2<String,CustomerRequest>> getCustomerRequestData(final String productId, PreparedStatement ps, final String receiptPeriod, String pagingState)
{
final int PAGE_SIZE = 10;
session = cassandraSessionFactory.getSession();
final List<CustomerRequest> customerRequestdata = new ArrayList<CustomerRequest>();
try
{
final BoundStatement boundStatement = ps.bind(productId, receiptPeriod, PAGE_SIZE);
boundStatement.setPagingState(PagingState.fromString(pagingState));
final ResultSet resultSet = session.execute(boundStatement);
final Iterator<Row> iter = resultSet.iterator();
final PagingState nextPage = resultSet.getExecutionInfo().getPagingState();
int remaining = resultSet.getAvailableWithoutFetching();
for (final Row rowdt : resultSet)
{
customerRequestdata.add(constructCustomerReq(rowdt));
if (--remaining == 0)
{
break;
}
}
}
catch (final Exception e)
{
e.printStackTrace();
}
return new Tuple2<>(nextPage.toString(), customerRe);
Please note the use of Tuple2 class to return the list of results as well as the paging state, serialized as a String to be passed easily to the front-end
I have the following SQL query:
SELECT CONNECTIONDATE AS UNLOAD,
SUBSTR(ROUTECODE,1,(LENGTH(ROUTECODE)-2)) AS ROUTE,
COUNT(SUBSTR(ROUTECODE,1,(LENGTH(ROUTECODE)-2))) AS FREQUENCY
FROM RouteTableSynonym RC1
WHERE RC1.ROUTECONNECTIONTYPE = 'INBOUND'
and RC1.CONNECTIONTIME >= TO_TIMESTAMP('<sdate>', 'DD-MM-YYYY HH24:MI:SS')
and RC1.CONNECTIONTIME <= TO_TIMESTAMP('<edate>', 'DD-MM-YYYY HH24:MI:SS')
and RC1.LOGISTICSPOINTID in (SELECT DISTINCT RCO1.LOGISTICSPOINTID
FROM RouteOrderTableSynonym RCO1
WHERE RCO1.NAMC = '<namc>')
GROUP BY CONNECTIONDATE, SUBSTR(ROUTECODE,1,(LENGTH(ROUTECODE)-2))
ORDER BY CONNECTIONDATE, ROUTE;
All values designated by '<var_name>' are replace with the values that being queried. I also have this entity class that will store the result of this query:
import java.util.Date;
public class DD_BlackoutRouteFrequencies {
private Date rte_day;
private String route;
private int freq;
private int delayedFreq;
public Date getRte_day() {
return rte_day;
}
public void setRte_day(Date rte_day) {
this.rte_day = rte_day;
}
public String getRoute() {
return route;
}
public void setRoute(String route) {
this.route = route;
}
public int getFreq() {
return freq;
}
public void setFreq(int freq) {
this.freq = freq;
}
public int getDelayedFreq() {
return delayedFreq;
}
public void setDelayedFreq(int delayedFreq) {
this.delayedFreq = delayedFreq;
}
}
I execute the query like this :
try{
SQLQuery sqlquery = session.createSQLQuery(query);
sqlquery.addEntity(DD_BlackoutRouteFrequencies.class);
results = sqlquery.list();
logger.debug(results.size());
System.out.println("Frequnecy Results size: "+results.size());
}catch(Exception e){
logger.error("Exception ", e);
throw new RuntimeException("SQL Exception getting Blackout Route Frequencies: "+ e.getMessage());
}
The problem I am having is that I cannot figure out how to do the hibernate mapping for this entity to receive the results of this query which draws its results from two different tables.
Do I have to do the hibernate mapping for both table used in the query and then map the entity?
You can also get an instance of a map. e.g.:
SQLQuery sqlQuery = session.createSQLQuery(sql);
// positional parameters (using ?)
sqlQuery.setString(0, sdate);
sqlQuery.setString(1, edate);
sqlQuery.setString(2, namc);
// scalar values for each column
sqlQuery.addScalar("UNLOAD", Hibernate.STRING);
sqlQuery.addScalar("ROUTE", Hibernate.STRING);
sqlQuery.addScalar("FREQUENCY ", Hibernate.INTEGER);
sqlQuery.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
List<Map<String, Object>> list = sqlQuery.list();
for (Map<String, Object> map : list) {
System.out.println(map.get("UNLOAD"));
System.out.println(map.get("ROUTE"));
System.out.println(map.get("FREQUENCY"));
}
I use mybatis to perform sql queries in my project. I need to intercept sql query before executing to apply some changed dynamically. I've read about #Interseptors like this:
#Intercepts({#Signature(type= Executor.class, method = "query", args = {...})})
public class ExamplePlugin implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
return invocation.proceed();
}
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties) {
}
}
And it really intercepts executions, but there is no way to change sql query since appropriate field is not writable. Should I build new instance of whole object manually to just replace sql query? Where is the right place to intercept query execution to change it dynamically? Thank.
I hope it will help you:
#Intercepts( { #Signature(type = Executor.class, method = "query", args = {
MappedStatement.class, Object.class, RowBounds.class,
ResultHandler.class
})
})
public class SelectCountSqlInterceptor2 implements Interceptor
{
public static String COUNT = "_count";
private static int MAPPED_STATEMENT_INDEX = 0;
private static int PARAMETER_INDEX = 1;
#Override
public Object intercept(Invocation invocation) throws Throwable
{
processCountSql(invocation.getArgs());
return invocation.proceed();
}
#SuppressWarnings("rawtypes")
private void processCountSql(final Object[] queryArgs)
{
if (queryArgs[PARAMETER_INDEX] instanceof Map)
{
Map parameter = (Map) queryArgs[PARAMETER_INDEX];
if (parameter.containsKey(COUNT))
{
MappedStatement ms = (MappedStatement) queryArgs[MAPPED_STATEMENT_INDEX];
BoundSql boundSql = ms.getBoundSql(parameter);
String sql = ms.getBoundSql(parameter).getSql().trim();
BoundSql newBoundSql = new BoundSql(ms.getConfiguration(),
getCountSQL(sql), boundSql.getParameterMappings(),
boundSql.getParameterObject());
MappedStatement newMs = copyFromMappedStatement(ms,
new OffsetLimitInterceptor.BoundSqlSqlSource(newBoundSql));
queryArgs[MAPPED_STATEMENT_INDEX] = newMs;
}
}
}
// see: MapperBuilderAssistant
#SuppressWarnings({ "unchecked", "rawtypes" })
private MappedStatement copyFromMappedStatement(MappedStatement ms,
SqlSource newSqlSource)
{
Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms
.getId(), newSqlSource, ms.getSqlCommandType());
builder.resource(ms.getResource());
builder.fetchSize(ms.getFetchSize());
builder.statementType(ms.getStatementType());
builder.keyGenerator(ms.getKeyGenerator());
// setStatementTimeout()
builder.timeout(ms.getTimeout());
// setParameterMap()
builder.parameterMap(ms.getParameterMap());
// setStatementResultMap()
List<ResultMap> resultMaps = new ArrayList<ResultMap>();
String id = "-inline";
if (ms.getResultMaps() != null)
{
id = ms.getResultMaps().get(0).getId() + "-inline";
}
ResultMap resultMap = new ResultMap.Builder(null, id, Long.class,
new ArrayList()).build();
resultMaps.add(resultMap);
builder.resultMaps(resultMaps);
builder.resultSetType(ms.getResultSetType());
// setStatementCache()
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());
return builder.build();
}
private String getCountSQL(String sql)
{
String lowerCaseSQL = sql.toLowerCase().replace("\n", " ").replace("\t", " ");
int index = lowerCaseSQL.indexOf(" order ");
if (index != -1)
{
sql = sql.substring(0, index);
}
return "SELECT COUNT(*) from ( select 1 as col_c " + sql.substring(lowerCaseSQL.indexOf(" from ")) + " ) cnt";
}
#Override
public Object plugin(Object target)
{
return Plugin.wrap(target, this);
}
#Override
public void setProperties(Properties properties)
{
}
}
You may consider using a string template library (eg Velocity, Handlebars, Mustache) to help you
As of to date, there is even MyBatis-Velocity (http://mybatis.github.io/velocity-scripting/) to help you to do scripting for the sql.
Depending on the changes you want to make, you may want to use the dynamic sql feature of mybatis 3